Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #67 #68

Merged
merged 11 commits into from
Jan 24, 2024
20 changes: 20 additions & 0 deletions configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ type Configuration interface {
// GetConfiguration retrieves the configurations/property sources of an application based on the name of the application
// and the profiles of the application.
GetConfiguration(applicationName string, profiles ...string) (Source, error)
// GetConfigurationWithLabel retrieves the configurations/property sources of an application based on the name of the application
// and the profiles of the application and the label.
GetConfigurationWithLabel(label string, applicationName string, profiles ...string) (Source, error)
}

// GetConfiguration retrieves the configurations/property sources of an application based on the name of the application
Expand All @@ -171,6 +174,23 @@ func (c *Client) GetConfiguration(applicationName string, profiles ...string) (S
return Source{}, fmt.Errorf("failed to find configuration for application %s with profiles %s", applicationName, profiles)
}

// GetConfigurationWithLabel retrieves the configurations/property sources of an application based on the name of the application
// and the profiles of the application and the label.
func (c *Client) GetConfigurationWithLabel(label string, applicationName string, profiles ...string) (Source, error) {
var source Source
paths := []string{applicationName, joinProfiles(profiles), label}
for _, client := range c.clients {
if err := client.GetResource(paths, nil, &source); err != nil {
if errors.Is(err, ErrResourceNotFound) {
continue
}
return Source{}, err
}
return source, nil
}
return Source{}, fmt.Errorf("failed to find configuration for application %s with profiles %s and label %s", applicationName, profiles, label)
}

func joinProfiles(profiles []string) string {
return strings.Join(profiles, ",")
}
94 changes: 94 additions & 0 deletions configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,100 @@ func TestClient_GetConfiguration(t *testing.T) {
})
}
}
func TestClient_GetConfigurationWithLabel(t *testing.T) {
tests := []struct {
name string
label string
application string
profiles []string
checker func(*testing.T, *http.Request)
response *http.Response
expected cloudconfigclient.Source
err error
}{
{
name: "Get Config",
label: "master",
application: "appName",
profiles: []string{"profile"},
checker: func(t *testing.T, request *http.Request) {
require.Equal(t, "http://localhost:8888/appName/profile/master", request.URL.String())
},
response: NewMockHttpResponse(http.StatusOK, configurationSource),
expected: cloudconfigclient.Source{
Name: "testConfig",
Profiles: []string{"profile"},
PropertySources: []cloudconfigclient.PropertySource{{Name: "test", Source: map[string]interface{}{"field1": "value1", "field2": float64(1)}}},
},
},
{
name: "Multiple Profiles",
label: "master",
application: "appName",
profiles: []string{"profile1", "profile2", "profile3"},
checker: func(t *testing.T, request *http.Request) {
require.Equal(t, "http://localhost:8888/appName/profile1,profile2,profile3/master", request.URL.String())
},
response: NewMockHttpResponse(http.StatusOK, configurationSource),
expected: cloudconfigclient.Source{
Name: "testConfig",
Profiles: []string{"profile"},
PropertySources: []cloudconfigclient.PropertySource{{Name: "test", Source: map[string]interface{}{"field1": "value1", "field2": float64(1)}}},
},
},
{
name: "Not Found",
label: "master",
application: "appName",
profiles: []string{"profile"},
response: NewMockHttpResponse(http.StatusNotFound, ""),
err: errors.New("failed to find configuration for application appName with profiles [profile] and label master"),
},
{
name: "Server Error",
label: "master",
application: "appName",
profiles: []string{"profile"},
response: NewMockHttpResponse(http.StatusInternalServerError, ""),
err: errors.New("server responded with status code '500' and body ''"),
},
{
name: "No Response Body",
label: "master",
application: "appName",
profiles: []string{"profile"},
response: NewMockHttpResponse(http.StatusOK, ""),
err: errors.New("failed to decode response from url: EOF"),
},
{
name: "HTTP Error",
label: "master",
application: "appName",
profiles: []string{"profile"},
err: errors.New("failed to retrieve from http://localhost:8888/appName/profile/master: Get \"http://localhost:8888/appName/profile/master\": http: RoundTripper implementation (cloudconfigclient_test.RoundTripFunc) returned a nil *Response with a nil error"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
httpClient := NewMockHttpClient(func(req *http.Request) *http.Response {
if test.checker != nil {
test.checker(t, req)
}
return test.response
})
client, err := cloudconfigclient.New(cloudconfigclient.Local(httpClient, "http://localhost:8888"))
require.NoError(t, err)
configuration, err := client.GetConfigurationWithLabel(test.label, test.application, test.profiles...)
if err != nil {
require.Error(t, err)
require.Equal(t, test.err.Error(), err.Error())
} else {
require.NoError(t, err)
require.Equal(t, test.expected, configuration)
}
})
}
}

func TestSource_GetPropertySource(t *testing.T) {
source := cloudconfigclient.Source{
Expand Down
Loading