Skip to content

Commit 79b362e

Browse files
authored
refactor: rename flag-source-url to provider-url for consistency (#181)
Signed-off-by: Michael Beemer <[email protected]>
1 parent 8b8f23d commit 79b362e

File tree

9 files changed

+173
-91
lines changed

9 files changed

+173
-91
lines changed

docs/commands/openfeature_init.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ openfeature init [flags]
1515
### Options
1616

1717
```
18-
--flag-source-url string The URL of the flag source
19-
-h, --help help for init
20-
--override Override an existing configuration
18+
-h, --help help for init
19+
--override Override an existing configuration
20+
--provider-url string The URL of the flag provider
2121
```
2222

2323
### Options inherited from parent commands

docs/commands/openfeature_pull.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ openfeature pull [flags]
3636
### Options
3737

3838
```
39-
--auth-token string The auth token for the flag source
40-
--flag-source-url string The URL of the flag source
41-
-h, --help help for pull
42-
--no-prompt Disable interactive prompts for missing default values
39+
--auth-token string The auth token for the flag provider
40+
-h, --help help for pull
41+
--no-prompt Disable interactive prompts for missing default values
42+
--provider-url string The URL of the flag provider
4343
```
4444

4545
### Options inherited from parent commands

docs/commands/openfeature_push.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,25 @@ openfeature push [flags]
4040

4141
```
4242
# Push flags to a remote HTTPS endpoint (smart push: creates and updates as needed)
43-
openfeature push --flag-source-url https://api.example.com --auth-token secret-token
43+
openfeature push --provider-url https://api.example.com --auth-token secret-token
4444
4545
# Push flags to an HTTP endpoint (development)
46-
openfeature push --flag-source-url http://localhost:8080
46+
openfeature push --provider-url http://localhost:8080
4747
4848
# Dry run to preview what would be sent
49-
openfeature push --flag-source-url https://api.example.com --dry-run
49+
openfeature push --provider-url https://api.example.com --dry-run
5050
```
5151

5252
### Options
5353

5454
```
55-
--auth-token string The auth token for the flag destination
56-
--debug Enable debug logging
57-
--dry-run Preview changes without pushing
58-
--flag-source-url string The URL of the flag destination
59-
-h, --help help for push
60-
-m, --manifest string Path to the flag manifest (default "flags.json")
61-
--no-input Disable interactive prompts
55+
--auth-token string The auth token for the flag provider
56+
--debug Enable debug logging
57+
--dry-run Preview changes without pushing
58+
-h, --help help for push
59+
-m, --manifest string Path to the flag manifest (default "flags.json")
60+
--no-input Disable interactive prompts
61+
--provider-url string The URL of the flag provider
6262
```
6363

6464
### SEE ALSO

internal/cmd/init.go

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ func GetInitCmd() *cobra.Command {
2424
RunE: func(cmd *cobra.Command, args []string) error {
2525
manifestPath := config.GetManifestPath(cmd)
2626
override := config.GetOverride(cmd)
27-
flagSourceUrl := config.GetFlagSourceUrl(cmd)
27+
providerUrl := config.GetFlagSourceUrl(cmd)
2828

2929
if err := handleManifestCreation(manifestPath, override); err != nil {
3030
return err
3131
}
3232

33-
if err := handleConfigFile(flagSourceUrl, override); err != nil {
33+
if err := handleConfigFile(providerUrl, override); err != nil {
3434
return err
3535
}
3636

@@ -84,46 +84,46 @@ func handleManifestCreation(manifestPath string, override bool) error {
8484
return nil
8585
}
8686

87-
func handleConfigFile(flagSourceUrl string, override bool) error {
87+
func handleConfigFile(providerURL string, override bool) error {
8888
configPath := ".openfeature.yaml"
8989
configExists, err := filesystem.Exists(configPath)
9090
if err != nil {
9191
return fmt.Errorf("failed to check if config file exists: %w", err)
9292
}
9393

9494
if !configExists {
95-
return writeConfigFile(flagSourceUrl, "Creating .openfeature.yaml configuration file")
95+
return writeConfigFile(providerURL, "Creating .openfeature.yaml configuration file")
9696
}
9797

98-
if flagSourceUrl == "" {
98+
if providerURL == "" {
9999
return nil // no config to write
100100
}
101101

102102
if override {
103-
return writeConfigFile(flagSourceUrl, "Updating flag source URL in .openfeature.yaml")
103+
return writeConfigFile(providerURL, "Updating provider URL in .openfeature.yaml")
104104
}
105105

106106
shouldOverride, err := confirmOverride("configuration file", configPath)
107107
if err != nil {
108108
return fmt.Errorf("failed to get user confirmation: %w", err)
109109
}
110110
if shouldOverride {
111-
return writeConfigFile(flagSourceUrl, "Updating flag source URL in .openfeature.yaml")
111+
return writeConfigFile(providerURL, "Updating provider URL in .openfeature.yaml")
112112
}
113113

114114
logger.Default.Info("Configuration file was not modified.")
115115
return nil
116116
}
117117

118-
func writeConfigFile(flagSourceUrl, message string) error {
119-
pterm.Info.Println(message, pterm.LightWhite(flagSourceUrl))
120-
template := getConfigTemplate(flagSourceUrl)
118+
func writeConfigFile(providerURL, message string) error {
119+
pterm.Info.Println(message, pterm.LightWhite(providerURL))
120+
template := getConfigTemplate(providerURL)
121121
return filesystem.WriteFile(".openfeature.yaml", []byte(template))
122122
}
123123

124124
type configTemplateData struct {
125-
FlagSourceURL string
126-
HasFlagSourceURL bool
125+
ProviderURL string
126+
HasProviderURL bool
127127
}
128128

129129
const configTemplateText = `# OpenFeature CLI Configuration
@@ -134,11 +134,11 @@ const configTemplateText = `# OpenFeature CLI Configuration
134134
# Path to your flag manifest file (default: "flags.json")
135135
# manifest: "flags.json"
136136
137-
# URL of your flag source for the 'pull' command
138-
# Supports http://, https://, and file:// protocols
139-
{{if .HasFlagSourceURL}}flagSourceURL: {{.FlagSourceURL}}{{else}}# flagSourceUrl: "https://your-flag-service.com/api/flags"{{end}}
137+
# URL of your flag provider for the 'pull' and 'push' commands
138+
# Supports http://, https://, and file:// protocols (file:// only for pull)
139+
{{if .HasProviderURL}}provider: {{.ProviderURL}}{{else}}# provider: "https://your-flag-service.com/api/flags"{{end}}
140140
141-
# Authentication token for remote flag sources (if required)
141+
# Authentication token for remote flag providers (if required)
142142
# authToken: "your-bearer-token"
143143
144144
# Enable debug logging (default: false)
@@ -151,36 +151,41 @@ const configTemplateText = `# OpenFeature CLI Configuration
151151
# Override global settings for specific commands
152152
153153
# pull:
154-
# flag-source-url: "https://api.example.com/flags"
154+
# provider: "https://api.example.com/flags"
155155
# auth-token: "pull-specific-token"
156156
# no-prompt: false
157157
158+
# push:
159+
# provider: "https://api.example.com/flags"
160+
# auth-token: "push-specific-token"
161+
# dry-run: false
162+
158163
# generate:
159164
# output: "generated"
160-
#
165+
#
161166
# # Language-specific generator options
162167
# go:
163168
# output: "go/flags"
164169
# package-name: "openfeature"
165-
#
170+
#
166171
# typescript:
167172
# output: "ts/flags"
168-
#
173+
#
169174
# csharp:
170175
# output: "csharp/flags"
171176
# namespace: "OpenFeature"
172-
#
177+
#
173178
# java:
174179
# output: "java/flags"
175180
# package-name: "com.example.openfeature"
176181
`
177182

178-
func getConfigTemplate(flagSourceUrl string) string {
183+
func getConfigTemplate(providerURL string) string {
179184
tmpl := template.Must(template.New("config").Parse(configTemplateText))
180185

181186
data := configTemplateData{
182-
FlagSourceURL: flagSourceUrl,
183-
HasFlagSourceURL: flagSourceUrl != "",
187+
ProviderURL: providerURL,
188+
HasProviderURL: providerURL != "",
184189
}
185190

186191
var buf bytes.Buffer

internal/cmd/pull.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,17 @@ Why pull from a remote source:
4242
return initializeConfig(cmd, "pull")
4343
},
4444
RunE: func(cmd *cobra.Command, args []string) error {
45-
flagSourceUrl := config.GetFlagSourceUrl(cmd)
45+
providerURL := config.GetFlagSourceUrl(cmd)
4646
manifestPath := config.GetManifestPath(cmd)
4747
authToken := config.GetAuthToken(cmd)
4848
noPrompt := config.GetNoPrompt(cmd)
4949

50-
if flagSourceUrl == "" {
51-
return fmt.Errorf("flagSourceUrl not set in config")
50+
if providerURL == "" {
51+
return fmt.Errorf("provider URL not set in config. Please provide --provider-url or set 'provider' in .openfeature.yaml")
5252
}
5353

5454
// fetch the flags from the remote source
55-
parsedURL, err := url.Parse(flagSourceUrl)
55+
parsedURL, err := url.Parse(providerURL)
5656
if err != nil {
5757
return fmt.Errorf("invalid URL: %w", err)
5858
}
@@ -69,14 +69,14 @@ Why pull from a remote source:
6969
urlContainsAFileExtension := manifest.URLLooksLikeAFile(parsedURL.String())
7070
if urlContainsAFileExtension {
7171
// Use direct HTTP requests for pulling flags from file-like URLs
72-
loadedFlags, err := manifest.LoadFromRemote(flagSourceUrl, authToken)
72+
loadedFlags, err := manifest.LoadFromRemote(providerURL, authToken)
7373
if err != nil {
7474
return fmt.Errorf("error fetching flags from remote source: %w", err)
7575
}
7676
flags = loadedFlags
7777
} else {
7878
// Use the sync API client for pulling flags
79-
loadedFlags, err := manifest.LoadFromSyncAPI(flagSourceUrl, authToken)
79+
loadedFlags, err := manifest.LoadFromSyncAPI(providerURL, authToken)
8080
if err != nil {
8181
return fmt.Errorf("error fetching flags from remote source: %w", err)
8282
}
@@ -101,7 +101,7 @@ Why pull from a remote source:
101101
}
102102
}
103103

104-
pterm.Success.Printfln("Successfully fetched flags from %s", flagSourceUrl)
104+
pterm.Success.Printfln("Successfully fetched flags from %s", providerURL)
105105
if err := manifest.Write(manifestPath, *flags); err != nil {
106106
return fmt.Errorf("error writing manifest: %w", err)
107107
}

internal/cmd/pull_test.go

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func setupTest(t *testing.T) afero.Fs {
2121
}
2222

2323
func TestPull(t *testing.T) {
24-
t.Run("pull no flag source url", func(t *testing.T) {
24+
t.Run("pull no provider url", func(t *testing.T) {
2525
setupTest(t)
2626
cmd := GetPullCmd()
2727

@@ -35,10 +35,10 @@ func TestPull(t *testing.T) {
3535
// Run command
3636
err := cmd.Execute()
3737
assert.Error(t, err)
38-
assert.Contains(t, err.Error(), "flagSourceUrl not set in config")
38+
assert.Contains(t, err.Error(), "provider URL not set in config")
3939
})
4040

41-
t.Run("pull with flag source url", func(t *testing.T) {
41+
t.Run("pull with provider url", func(t *testing.T) {
4242
fs := setupTest(t)
4343
defer gock.Off()
4444

@@ -74,7 +74,7 @@ func TestPull(t *testing.T) {
7474
// Prepare command arguments - use base URL only
7575
args := []string{
7676
"pull",
77-
"--flag-source-url", "https://example.com",
77+
"--provider-url", "https://example.com",
7878
"--manifest", "manifest/path.json",
7979
}
8080

@@ -124,7 +124,7 @@ func TestPull(t *testing.T) {
124124
// Prepare command arguments - use base URL only
125125
args := []string{
126126
"pull",
127-
"--flag-source-url", "https://example.com",
127+
"--provider-url", "https://example.com",
128128
"--manifest", "manifest/path.json",
129129
}
130130

@@ -165,7 +165,7 @@ func TestPull(t *testing.T) {
165165
// Prepare command arguments - URL with .json extension
166166
args := []string{
167167
"pull",
168-
"--flag-source-url", "https://example.com/flags.json",
168+
"--provider-url", "https://example.com/flags.json",
169169
"--manifest", "manifest/path.json",
170170
}
171171

@@ -218,7 +218,7 @@ func TestPull(t *testing.T) {
218218
// Prepare command arguments - URL with .yaml extension
219219
args := []string{
220220
"pull",
221-
"--flag-source-url", "https://example.com/flags.yaml",
221+
"--provider-url", "https://example.com/flags.yaml",
222222
"--manifest", "manifest/path.json",
223223
}
224224

@@ -271,7 +271,7 @@ func TestPull(t *testing.T) {
271271
// Prepare command arguments - URL with .yml extension
272272
args := []string{
273273
"pull",
274-
"--flag-source-url", "https://example.com/config.yml",
274+
"--provider-url", "https://example.com/config.yml",
275275
"--manifest", "manifest/path.json",
276276
}
277277

@@ -325,7 +325,7 @@ func TestPull(t *testing.T) {
325325
// Prepare command arguments - base URL without file extension
326326
args := []string{
327327
"pull",
328-
"--flag-source-url", "https://api.example.com",
328+
"--provider-url", "https://api.example.com",
329329
"--manifest", "manifest/path.json",
330330
}
331331

@@ -348,4 +348,58 @@ func TestPull(t *testing.T) {
348348
_, exists := flags["syncApiFlag"]
349349
assert.True(t, exists, "Flag syncApiFlag should exist in manifest")
350350
})
351+
352+
t.Run("backward compatibility with deprecated --flag-source-url", func(t *testing.T) {
353+
fs := setupTest(t)
354+
defer gock.Off()
355+
356+
// Mock response in OpenAPI ManifestEnvelope format
357+
manifestResponse := map[string]any{
358+
"flags": []map[string]any{
359+
{
360+
"key": "backwardCompatFlag",
361+
"type": "boolean",
362+
"defaultValue": true,
363+
"description": "Test backward compatibility",
364+
},
365+
},
366+
}
367+
368+
// Mock the sync API endpoint
369+
gock.New("https://example.com").
370+
Get("/openfeature/v0/manifest").
371+
Reply(200).
372+
JSON(manifestResponse)
373+
374+
cmd := GetPullCmd()
375+
376+
// global flag exists on root only.
377+
config.AddRootFlags(cmd)
378+
379+
// Use the deprecated flag to test backward compatibility
380+
args := []string{
381+
"pull",
382+
"--flag-source-url", "https://example.com",
383+
"--manifest", "manifest/path.json",
384+
}
385+
386+
cmd.SetArgs(args)
387+
388+
// Run command - should work but show deprecation warning
389+
err := cmd.Execute()
390+
assert.NoError(t, err)
391+
392+
// Verify the manifest was written correctly
393+
content, err := afero.ReadFile(fs, "manifest/path.json")
394+
assert.NoError(t, err)
395+
396+
var manifestFlags map[string]interface{}
397+
err = json.Unmarshal(content, &manifestFlags)
398+
assert.NoError(t, err)
399+
400+
// Verify the flag exists in the manifest
401+
flags := manifestFlags["flags"].(map[string]interface{})
402+
_, exists := flags["backwardCompatFlag"]
403+
assert.True(t, exists, "Flag backwardCompatFlag should exist in manifest")
404+
})
351405
}

0 commit comments

Comments
 (0)