Skip to content

Commit 505ac0d

Browse files
Improve tiger auth status output (#106)
1 parent f2bb5e4 commit 505ac0d

20 files changed

Lines changed: 722 additions & 381 deletions

.env.sample

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
# Tiger Cloud API credentials for integration testing
55
TIGER_PUBLIC_KEY_INTEGRATION=your-public-key-here
6-
TIGER_SECRET_KEY_INTEGRATION=your-secret-key-here
7-
TIGER_PROJECT_ID_INTEGRATION=your-project-id-here
6+
TIGER_SECRET_KEY_INTEGRATION=your-secret-key-here
87

98
# Optional: Use existing service for database tests (to avoid creating new services)
109
# TIGER_EXISTING_SERVICE_ID_INTEGRATION=existing-service-id-here
@@ -13,4 +12,4 @@ TIGER_PROJECT_ID_INTEGRATION=your-project-id-here
1312
TIGER_API_URL_INTEGRATION=http://localhost:8080/public/api/v1
1413

1514
# To use these integration variables for regular CLI commands (auth login, etc.):
16-
# export $(cat .env.prod.test | sed 's/_INTEGRATION//' | xargs)
15+
# export $(cat .env.prod.test | sed 's/_INTEGRATION//' | xargs)

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ go test ./internal/tiger/cmd -run Integration
100100
# To run integration tests with real API calls, set environment variables:
101101
export TIGER_PUBLIC_KEY_INTEGRATION=your-public-key
102102
export TIGER_SECRET_KEY_INTEGRATION=your-secret-key
103-
export TIGER_PROJECT_ID_INTEGRATION=your-project-id
104103
export TIGER_API_URL_INTEGRATION=http://localhost:8080/public/api/v1
105104

106105
# Optional: Set this to test database commands with existing service

docs/development.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ Integration tests execute real API calls against a Tiger environment to validate
6868
```bash
6969
TIGER_PUBLIC_KEY_INTEGRATION=your-public-key-here
7070
TIGER_SECRET_KEY_INTEGRATION=your-secret-key-here
71-
TIGER_PROJECT_ID_INTEGRATION=your-project-id-here
7271
TIGER_API_URL=http://localhost:8080/public/api/v1 # or production URL
7372
```
7473

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
go.uber.org/zap v1.27.0
2525
golang.org/x/oauth2 v0.31.0
2626
golang.org/x/term v0.35.0
27+
golang.org/x/text v0.29.0
2728
gopkg.in/yaml.v3 v3.0.1
2829
)
2930

@@ -161,7 +162,6 @@ require (
161162
golang.org/x/net v0.43.0 // indirect
162163
golang.org/x/sync v0.17.0 // indirect
163164
golang.org/x/sys v0.36.0 // indirect
164-
golang.org/x/text v0.29.0 // indirect
165165
golang.org/x/time v0.12.0 // indirect
166166
golang.org/x/tools v0.36.0 // indirect
167167
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect

internal/tiger/analytics/analytics.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func Error(err error) Option {
137137
// analytics. It automatically includes common properties like ProjectID. The
138138
// identification is only sent if the client is initialized and analytics are
139139
// enabled in the config, otherwise it is skipped.
140-
func (a *Analytics) Identify(event string, options ...Option) {
140+
func (a *Analytics) Identify(options ...Option) {
141141
// Create properties map with user-provided properties
142142
properties := map[string]any{}
143143
for _, option := range options {

internal/tiger/api/client.go

Lines changed: 110 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/tiger/api/client_util.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package api
33
import (
44
"context"
55
"encoding/base64"
6-
"errors"
76
"fmt"
87
"net/http"
98
"sync"
@@ -60,51 +59,6 @@ func NewTigerClient(cfg *config.Config, apiKey string) (*ClientWithResponses, er
6059
return client, nil
6160
}
6261

63-
// ValidateAPIKey validates the API key by making a test API call
64-
func ValidateAPIKey(ctx context.Context, cfg *config.Config, apiKey string, projectID string) error {
65-
client, err := NewTigerClient(cfg, apiKey)
66-
if err != nil {
67-
return fmt.Errorf("failed to create client: %w", err)
68-
}
69-
70-
return ValidateAPIKeyWithClient(ctx, client, projectID)
71-
}
72-
73-
// ValidateAPIKeyWithClient validates the API key using the provided client interface
74-
func ValidateAPIKeyWithClient(ctx context.Context, client ClientWithResponsesInterface, projectID string) error {
75-
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
76-
defer cancel()
77-
78-
// Use provided project ID if available, otherwise use a dummy one
79-
targetProjectID := projectID
80-
if targetProjectID == "" {
81-
// Use a dummy project ID for validation when none is provided
82-
targetProjectID = "00000000-0000-0000-0000-000000000000"
83-
}
84-
85-
// Try to call a simple endpoint
86-
// The API should return 401/403 for invalid API key, and 404 for non-existent project
87-
resp, err := client.GetProjectsProjectIdServicesWithResponse(ctx, targetProjectID)
88-
if err != nil {
89-
return fmt.Errorf("API call failed: %w", err)
90-
}
91-
92-
// Check the response status
93-
if resp.StatusCode() != 200 {
94-
if resp.StatusCode() == 404 {
95-
// Project not found, but API key is valid
96-
return nil
97-
}
98-
if resp.JSON4XX != nil {
99-
return resp.JSON4XX
100-
} else {
101-
return errors.New("unexpected API response: 500")
102-
}
103-
} else {
104-
return nil
105-
}
106-
}
107-
10862
// Error implements the error interface for the Error type.
10963
// This allows Error values to be used directly as Go errors.
11064
func (e *Error) Error() string {

internal/tiger/api/client_util_test.go

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -7,122 +7,9 @@ import (
77
"testing"
88

99
"github.com/timescale/tiger-cli/internal/tiger/api"
10-
"github.com/timescale/tiger-cli/internal/tiger/api/mocks"
1110
"github.com/timescale/tiger-cli/internal/tiger/config"
12-
"github.com/timescale/tiger-cli/internal/tiger/util"
13-
"go.uber.org/mock/gomock"
1411
)
1512

16-
func TestValidateAPIKeyWithClient(t *testing.T) {
17-
tests := []struct {
18-
name string
19-
setupMock func(*mocks.MockClientWithResponsesInterface)
20-
expectedError string
21-
}{
22-
{
23-
name: "valid API key - 200 response",
24-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
25-
m.EXPECT().
26-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
27-
Return(&api.GetProjectsProjectIdServicesResponse{
28-
HTTPResponse: &http.Response{StatusCode: 200},
29-
}, nil)
30-
},
31-
expectedError: "",
32-
},
33-
{
34-
name: "valid API key - 404 response (project not found)",
35-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
36-
m.EXPECT().
37-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
38-
Return(&api.GetProjectsProjectIdServicesResponse{
39-
HTTPResponse: &http.Response{StatusCode: 404},
40-
}, nil)
41-
},
42-
expectedError: "",
43-
},
44-
{
45-
name: "invalid API key - 401 response",
46-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
47-
m.EXPECT().
48-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
49-
Return(&api.GetProjectsProjectIdServicesResponse{
50-
HTTPResponse: &http.Response{StatusCode: 401},
51-
JSON4XX: &api.ClientError{Message: util.Ptr("Invalid or missing authentication credentials")},
52-
}, nil)
53-
},
54-
expectedError: "Invalid or missing authentication credentials",
55-
},
56-
{
57-
name: "invalid API key - 403 response",
58-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
59-
m.EXPECT().
60-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
61-
Return(&api.GetProjectsProjectIdServicesResponse{
62-
HTTPResponse: &http.Response{StatusCode: 403},
63-
JSON4XX: &api.ClientError{Message: util.Ptr("Invalid or missing authentication credentials")},
64-
}, nil)
65-
},
66-
expectedError: "Invalid or missing authentication credentials",
67-
},
68-
{
69-
name: "unexpected response - 500",
70-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
71-
m.EXPECT().
72-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
73-
Return(&api.GetProjectsProjectIdServicesResponse{
74-
HTTPResponse: &http.Response{StatusCode: 500},
75-
}, nil)
76-
},
77-
expectedError: "unexpected API response: 500",
78-
},
79-
{
80-
name: "network error",
81-
setupMock: func(m *mocks.MockClientWithResponsesInterface) {
82-
m.EXPECT().
83-
GetProjectsProjectIdServicesWithResponse(gomock.Any(), "00000000-0000-0000-0000-000000000000").
84-
Return(nil, context.DeadlineExceeded)
85-
},
86-
expectedError: "API call failed: context deadline exceeded",
87-
},
88-
}
89-
90-
for _, tt := range tests {
91-
t.Run(tt.name, func(t *testing.T) {
92-
ctrl := gomock.NewController(t)
93-
defer ctrl.Finish()
94-
95-
mockClient := mocks.NewMockClientWithResponsesInterface(ctrl)
96-
tt.setupMock(mockClient)
97-
98-
err := api.ValidateAPIKeyWithClient(context.Background(), mockClient, "")
99-
100-
if tt.expectedError == "" {
101-
if err != nil {
102-
t.Errorf("Expected no error, got: %v", err)
103-
}
104-
} else {
105-
if err == nil {
106-
t.Errorf("Expected error containing %q, got nil", tt.expectedError)
107-
} else if err.Error() != tt.expectedError {
108-
t.Errorf("Expected error %q, got %q", tt.expectedError, err.Error())
109-
}
110-
}
111-
})
112-
}
113-
}
114-
115-
// TestValidateAPIKey_Integration would be an integration test that actually calls the API
116-
// This should be run with a real API key for integration testing
117-
func TestValidateAPIKey_Integration(t *testing.T) {
118-
if testing.Short() {
119-
t.Skip("Skipping integration test in short mode")
120-
}
121-
122-
// This test would require a real API key and network connectivity
123-
t.Skip("Integration test requires real API key - implement when needed")
124-
}
125-
12613
func TestNewTigerClientUserAgent(t *testing.T) {
12714
// Create a test server that captures the User-Agent header
12815
var capturedUserAgent string

0 commit comments

Comments
 (0)