Skip to content

Commit 7ba1d0c

Browse files
authored
fix: Configuration values lost when user submits again after refresh … (#2445)
* fix: Configuration values lost when user submits again after refresh config page
1 parent 8412654 commit 7ba1d0c

File tree

25 files changed

+748
-257
lines changed

25 files changed

+748
-257
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ go.work.sum
1919
*.tmp
2020
.envrc
2121
.DS_Store
22+
CLAUDE.md
2223

2324
# Ignore preflight bundles generated during local dev
2425
preflightbundle*

api/client/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ type Client interface {
1717
SetupLinuxInfra(ignoreHostPreflights bool) (types.Infra, error)
1818
GetLinuxInfraStatus() (types.Infra, error)
1919
GetLinuxAppConfig() (types.AppConfig, error)
20+
GetLinuxAppConfigValues() (map[string]string, error)
2021

2122
GetKubernetesInstallationConfig() (types.KubernetesInstallationConfig, error)
2223
ConfigureKubernetesInstallation(config types.KubernetesInstallationConfig) (types.Status, error)
2324
GetKubernetesInstallationStatus() (types.Status, error)
2425
SetupKubernetesInfra() (types.Infra, error)
2526
GetKubernetesInfraStatus() (types.Infra, error)
2627
GetKubernetesAppConfig() (types.AppConfig, error)
28+
GetKubernetesAppConfigValues() (map[string]string, error)
2729
}
2830

2931
type client struct {

api/client/client_test.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,155 @@ func TestKubernetesGetAppConfig(t *testing.T) {
706706
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
707707
assert.Equal(t, "Internal Server Error", apiErr.Message)
708708
}
709+
710+
func TestLinuxGetAppConfigValues(t *testing.T) {
711+
// Define expected values once
712+
expectedValues := map[string]string{
713+
"test-key1": "test-value1",
714+
"test-key2": "test-value2",
715+
"test-key3": "test-value3",
716+
}
717+
718+
// Create a test server
719+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
720+
assert.Equal(t, "GET", r.Method)
721+
assert.Equal(t, "/api/linux/install/app/config/values", r.URL.Path)
722+
723+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
724+
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
725+
726+
// Return successful response
727+
w.WriteHeader(http.StatusOK)
728+
response := types.AppConfigValuesResponse{Values: expectedValues}
729+
json.NewEncoder(w).Encode(response)
730+
}))
731+
defer server.Close()
732+
733+
// Test successful get
734+
c := New(server.URL, WithToken("test-token"))
735+
values, err := c.GetLinuxAppConfigValues()
736+
assert.NoError(t, err)
737+
assert.Equal(t, expectedValues, values)
738+
739+
// Test authentication (without token)
740+
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
741+
assert.Equal(t, "GET", r.Method)
742+
assert.Equal(t, "/api/linux/install/app/config/values", r.URL.Path)
743+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
744+
assert.Empty(t, r.Header.Get("Authorization"))
745+
746+
// Return unauthorized response
747+
w.WriteHeader(http.StatusUnauthorized)
748+
json.NewEncoder(w).Encode(types.APIError{
749+
StatusCode: http.StatusUnauthorized,
750+
Message: "Unauthorized",
751+
})
752+
}))
753+
defer authServer.Close()
754+
755+
c = New(authServer.URL)
756+
values, err = c.GetLinuxAppConfigValues()
757+
assert.Error(t, err)
758+
assert.Nil(t, values)
759+
760+
apiErr, ok := err.(*types.APIError)
761+
require.True(t, ok, "Expected err to be of type *types.APIError")
762+
assert.Equal(t, http.StatusUnauthorized, apiErr.StatusCode)
763+
assert.Equal(t, "Unauthorized", apiErr.Message)
764+
765+
// Test error response
766+
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
767+
w.WriteHeader(http.StatusInternalServerError)
768+
json.NewEncoder(w).Encode(types.APIError{
769+
StatusCode: http.StatusInternalServerError,
770+
Message: "Internal Server Error",
771+
})
772+
}))
773+
defer errorServer.Close()
774+
775+
c = New(errorServer.URL, WithToken("test-token"))
776+
values, err = c.GetLinuxAppConfigValues()
777+
assert.Error(t, err)
778+
assert.Nil(t, values)
779+
780+
apiErr, ok = err.(*types.APIError)
781+
require.True(t, ok, "Expected err to be of type *types.APIError")
782+
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
783+
assert.Equal(t, "Internal Server Error", apiErr.Message)
784+
}
785+
786+
func TestKubernetesGetAppConfigValues(t *testing.T) {
787+
// Define expected values once
788+
expectedValues := map[string]string{
789+
"test-key1": "test-value1",
790+
"test-key2": "test-value2",
791+
"test-key3": "test-value3",
792+
}
793+
794+
// Create a test server
795+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
796+
assert.Equal(t, "GET", r.Method)
797+
assert.Equal(t, "/api/kubernetes/install/app/config/values", r.URL.Path)
798+
799+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
800+
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
801+
802+
// Return successful response
803+
w.WriteHeader(http.StatusOK)
804+
response := types.AppConfigValuesResponse{Values: expectedValues}
805+
json.NewEncoder(w).Encode(response)
806+
}))
807+
defer server.Close()
808+
809+
// Test successful get
810+
c := New(server.URL, WithToken("test-token"))
811+
values, err := c.GetKubernetesAppConfigValues()
812+
assert.NoError(t, err)
813+
assert.Equal(t, expectedValues, values)
814+
815+
// Test authentication (without token)
816+
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
817+
assert.Equal(t, "GET", r.Method)
818+
assert.Equal(t, "/api/kubernetes/install/app/config/values", r.URL.Path)
819+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
820+
assert.Empty(t, r.Header.Get("Authorization"))
821+
822+
// Return unauthorized response
823+
w.WriteHeader(http.StatusUnauthorized)
824+
json.NewEncoder(w).Encode(types.APIError{
825+
StatusCode: http.StatusUnauthorized,
826+
Message: "Unauthorized",
827+
})
828+
}))
829+
defer authServer.Close()
830+
831+
c = New(authServer.URL)
832+
values, err = c.GetKubernetesAppConfigValues()
833+
assert.Error(t, err)
834+
assert.Nil(t, values)
835+
836+
apiErr, ok := err.(*types.APIError)
837+
require.True(t, ok, "Expected err to be of type *types.APIError")
838+
assert.Equal(t, http.StatusUnauthorized, apiErr.StatusCode)
839+
assert.Equal(t, "Unauthorized", apiErr.Message)
840+
841+
// Test error response
842+
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
843+
w.WriteHeader(http.StatusInternalServerError)
844+
json.NewEncoder(w).Encode(types.APIError{
845+
StatusCode: http.StatusInternalServerError,
846+
Message: "Internal Server Error",
847+
})
848+
}))
849+
defer errorServer.Close()
850+
851+
c = New(errorServer.URL, WithToken("test-token"))
852+
values, err = c.GetKubernetesAppConfigValues()
853+
assert.Error(t, err)
854+
assert.Nil(t, values)
855+
856+
apiErr, ok = err.(*types.APIError)
857+
require.True(t, ok, "Expected err to be of type *types.APIError")
858+
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
859+
assert.Equal(t, "Internal Server Error", apiErr.Message)
860+
}

api/client/install.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,33 @@ func (c *client) GetLinuxAppConfig() (types.AppConfig, error) {
322322
return config, nil
323323
}
324324

325+
func (c *client) GetLinuxAppConfigValues() (map[string]string, error) {
326+
req, err := http.NewRequest("GET", c.apiURL+"/api/linux/install/app/config/values", nil)
327+
if err != nil {
328+
return nil, err
329+
}
330+
req.Header.Set("Content-Type", "application/json")
331+
setAuthorizationHeader(req, c.token)
332+
333+
resp, err := c.httpClient.Do(req)
334+
if err != nil {
335+
return nil, err
336+
}
337+
defer resp.Body.Close()
338+
339+
if resp.StatusCode != http.StatusOK {
340+
return nil, errorFromResponse(resp)
341+
}
342+
343+
var response types.AppConfigValuesResponse
344+
err = json.NewDecoder(resp.Body).Decode(&response)
345+
if err != nil {
346+
return nil, err
347+
}
348+
349+
return response.Values, nil
350+
}
351+
325352
func (c *client) GetKubernetesAppConfig() (types.AppConfig, error) {
326353
req, err := http.NewRequest("GET", c.apiURL+"/api/kubernetes/install/app/config", nil)
327354
if err != nil {
@@ -348,3 +375,30 @@ func (c *client) GetKubernetesAppConfig() (types.AppConfig, error) {
348375

349376
return config, nil
350377
}
378+
379+
func (c *client) GetKubernetesAppConfigValues() (map[string]string, error) {
380+
req, err := http.NewRequest("GET", c.apiURL+"/api/kubernetes/install/app/config/values", nil)
381+
if err != nil {
382+
return nil, err
383+
}
384+
req.Header.Set("Content-Type", "application/json")
385+
setAuthorizationHeader(req, c.token)
386+
387+
resp, err := c.httpClient.Do(req)
388+
if err != nil {
389+
return nil, err
390+
}
391+
defer resp.Body.Close()
392+
393+
if resp.StatusCode != http.StatusOK {
394+
return nil, errorFromResponse(resp)
395+
}
396+
397+
var response types.AppConfigValuesResponse
398+
err = json.NewDecoder(resp.Body).Decode(&response)
399+
if err != nil {
400+
return nil, err
401+
}
402+
403+
return response.Values, nil
404+
}

api/controllers/kubernetes/install/app.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,7 @@ func (c *InstallController) GetAppConfig(ctx context.Context) (kotsv1beta1.Confi
1515
return kotsv1beta1.Config{}, errors.New("app config not found")
1616
}
1717

18-
values, err := c.appConfigManager.GetConfigValues()
19-
if err != nil {
20-
return kotsv1beta1.Config{}, fmt.Errorf("get app config values: %w", err)
21-
}
22-
23-
appConfig, err := c.appConfigManager.ApplyValuesToConfig(*c.releaseData.AppConfig, values)
24-
if err != nil {
25-
return kotsv1beta1.Config{}, fmt.Errorf("apply values to config: %w", err)
26-
}
27-
28-
return appConfig, nil
18+
return *c.releaseData.AppConfig, nil
2919
}
3020

3121
func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
@@ -69,3 +59,7 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
6959

7060
return nil
7161
}
62+
63+
func (c *InstallController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
64+
return c.appConfigManager.GetConfigValues()
65+
}

api/controllers/kubernetes/install/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Controller interface {
2828
GetInfra(ctx context.Context) (types.Infra, error)
2929
GetAppConfig(ctx context.Context) (kotsv1beta1.Config, error)
3030
SetAppConfigValues(ctx context.Context, values map[string]string) error
31+
GetAppConfigValues(ctx context.Context) (map[string]string, error)
3132
}
3233

3334
var _ Controller = (*InstallController)(nil)

api/controllers/kubernetes/install/controller_mock.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,12 @@ func (m *MockController) SetAppConfigValues(ctx context.Context, values map[stri
6868
args := m.Called(ctx, values)
6969
return args.Error(0)
7070
}
71+
72+
// GetAppConfigValues mocks the GetAppConfigValues method
73+
func (m *MockController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
74+
args := m.Called(ctx)
75+
if args.Get(0) == nil {
76+
return nil, args.Error(1)
77+
}
78+
return args.Get(0).(map[string]string), args.Error(1)
79+
}

api/controllers/linux/install/app.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,7 @@ func (c *InstallController) GetAppConfig(ctx context.Context) (kotsv1beta1.Confi
1515
return kotsv1beta1.Config{}, errors.New("app config not found")
1616
}
1717

18-
values, err := c.appConfigManager.GetConfigValues()
19-
if err != nil {
20-
return kotsv1beta1.Config{}, fmt.Errorf("get app config values: %w", err)
21-
}
22-
23-
appConfig, err := c.appConfigManager.ApplyValuesToConfig(*c.releaseData.AppConfig, values)
24-
if err != nil {
25-
return kotsv1beta1.Config{}, fmt.Errorf("apply values to config: %w", err)
26-
}
27-
28-
return appConfig, nil
18+
return *c.releaseData.AppConfig, nil
2919
}
3020

3121
func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
@@ -69,3 +59,7 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
6959

7060
return nil
7161
}
62+
63+
func (c *InstallController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
64+
return c.appConfigManager.GetConfigValues()
65+
}

api/controllers/linux/install/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Controller interface {
3434
GetInfra(ctx context.Context) (types.Infra, error)
3535
GetAppConfig(ctx context.Context) (kotsv1beta1.Config, error)
3636
SetAppConfigValues(ctx context.Context, values map[string]string) error
37+
GetAppConfigValues(ctx context.Context) (map[string]string, error)
3738
}
3839

3940
type RunHostPreflightsOptions struct {

api/controllers/linux/install/controller_mock.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,12 @@ func (m *MockController) SetAppConfigValues(ctx context.Context, values map[stri
101101
args := m.Called(ctx, values)
102102
return args.Error(0)
103103
}
104+
105+
// GetAppConfigValues mocks the GetAppConfigValues method
106+
func (m *MockController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
107+
args := m.Called(ctx)
108+
if args.Get(0) == nil {
109+
return nil, args.Error(1)
110+
}
111+
return args.Get(0).(map[string]string), args.Error(1)
112+
}

0 commit comments

Comments
 (0)