Skip to content

Support the password config item type #2463

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Client interface {
GetLinuxInfraStatus() (types.Infra, error)
GetLinuxAppConfig() (types.AppConfig, error)
GetLinuxAppConfigValues() (map[string]string, error)
PatchLinuxAppConfigValues(values map[string]string) (types.AppConfig, error)

GetKubernetesInstallationConfig() (types.KubernetesInstallationConfig, error)
ConfigureKubernetesInstallation(config types.KubernetesInstallationConfig) (types.Status, error)
Expand All @@ -26,6 +27,7 @@ type Client interface {
GetKubernetesInfraStatus() (types.Infra, error)
GetKubernetesAppConfig() (types.AppConfig, error)
GetKubernetesAppConfigValues() (map[string]string, error)
PatchKubernetesAppConfigValues(values map[string]string) (types.AppConfig, error)
}

type client struct {
Expand Down
140 changes: 140 additions & 0 deletions api/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,3 +858,143 @@ func TestKubernetesGetAppConfigValues(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
assert.Equal(t, "Internal Server Error", apiErr.Message)
}

func TestLinuxPatchAppConfigValues(t *testing.T) {
// Define expected config once
expectedConfig := types.AppConfig{
Groups: []kotsv1beta1.ConfigGroup{
{
Name: "test-group",
Title: "Test Group",
Items: []kotsv1beta1.ConfigItem{
{
Name: "test-item",
Type: "text",
Title: "Test Item",
Default: multitype.BoolOrString{StrVal: "default"},
Value: multitype.BoolOrString{StrVal: "value"},
},
},
},
},
}

// Create a test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "PATCH", r.Method)
assert.Equal(t, "/api/linux/install/app/config/values", r.URL.Path)

assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))

// Decode and verify request body
var req types.PatchAppConfigValuesRequest
err := json.NewDecoder(r.Body).Decode(&req)
require.NoError(t, err)
assert.Equal(t, "new-value", req.Values["test-item"])

// Return successful response
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(expectedConfig)
}))
defer server.Close()

// Test successful set
c := New(server.URL, WithToken("test-token"))
values := map[string]string{
"test-item": "new-value",
}
config, err := c.PatchLinuxAppConfigValues(values)
assert.NoError(t, err)
assert.Equal(t, expectedConfig, config)

// Test error response
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(types.APIError{
StatusCode: http.StatusInternalServerError,
Message: "Internal Server Error",
})
}))
defer errorServer.Close()

c = New(errorServer.URL, WithToken("test-token"))
config, err = c.PatchLinuxAppConfigValues(values)
assert.Error(t, err)
assert.Equal(t, types.AppConfig{}, config)

apiErr, ok := err.(*types.APIError)
require.True(t, ok, "Expected err to be of type *types.APIError")
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
assert.Equal(t, "Internal Server Error", apiErr.Message)
}

func TestKubernetesPatchAppConfigValues(t *testing.T) {
// Define expected config once
expectedConfig := types.AppConfig{
Groups: []kotsv1beta1.ConfigGroup{
{
Name: "test-group",
Title: "Test Group",
Items: []kotsv1beta1.ConfigItem{
{
Name: "test-item",
Type: "text",
Title: "Test Item",
Default: multitype.BoolOrString{StrVal: "default"},
Value: multitype.BoolOrString{StrVal: "value"},
},
},
},
},
}

// Create a test server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "PATCH", r.Method)
assert.Equal(t, "/api/kubernetes/install/app/config/values", r.URL.Path)

assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))

// Decode and verify request body
var req types.PatchAppConfigValuesRequest
err := json.NewDecoder(r.Body).Decode(&req)
require.NoError(t, err)
assert.Equal(t, "new-value", req.Values["test-item"])

// Return successful response
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(expectedConfig)
}))
defer server.Close()

// Test successful set
c := New(server.URL, WithToken("test-token"))
values := map[string]string{
"test-item": "new-value",
}
config, err := c.PatchKubernetesAppConfigValues(values)
assert.NoError(t, err)
assert.Equal(t, expectedConfig, config)

// Test error response
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(types.APIError{
StatusCode: http.StatusInternalServerError,
Message: "Internal Server Error",
})
}))
defer errorServer.Close()

c = New(errorServer.URL, WithToken("test-token"))
config, err = c.PatchKubernetesAppConfigValues(values)
assert.Error(t, err)
assert.Equal(t, types.AppConfig{}, config)

apiErr, ok := err.(*types.APIError)
require.True(t, ok, "Expected err to be of type *types.APIError")
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
assert.Equal(t, "Internal Server Error", apiErr.Message)
}
70 changes: 70 additions & 0 deletions api/client/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,41 @@ func (c *client) GetLinuxAppConfigValues() (map[string]string, error) {
return response.Values, nil
}

func (c *client) PatchLinuxAppConfigValues(values map[string]string) (types.AppConfig, error) {
req := types.PatchAppConfigValuesRequest{
Values: values,
}
b, err := json.Marshal(req)
if err != nil {
return types.AppConfig{}, err
}

httpReq, err := http.NewRequest("PATCH", c.apiURL+"/api/linux/install/app/config/values", bytes.NewBuffer(b))
if err != nil {
return types.AppConfig{}, err
}
httpReq.Header.Set("Content-Type", "application/json")
setAuthorizationHeader(httpReq, c.token)

resp, err := c.httpClient.Do(httpReq)
if err != nil {
return types.AppConfig{}, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return types.AppConfig{}, errorFromResponse(resp)
}

var config types.AppConfig
err = json.NewDecoder(resp.Body).Decode(&config)
if err != nil {
return types.AppConfig{}, err
}

return config, nil
}

func (c *client) GetKubernetesAppConfig() (types.AppConfig, error) {
req, err := http.NewRequest("GET", c.apiURL+"/api/kubernetes/install/app/config", nil)
if err != nil {
Expand Down Expand Up @@ -402,3 +437,38 @@ func (c *client) GetKubernetesAppConfigValues() (map[string]string, error) {

return response.Values, nil
}

func (c *client) PatchKubernetesAppConfigValues(values map[string]string) (types.AppConfig, error) {
req := types.PatchAppConfigValuesRequest{
Values: values,
}
b, err := json.Marshal(req)
if err != nil {
return types.AppConfig{}, err
}

httpReq, err := http.NewRequest("PATCH", c.apiURL+"/api/kubernetes/install/app/config/values", bytes.NewBuffer(b))
if err != nil {
return types.AppConfig{}, err
}
httpReq.Header.Set("Content-Type", "application/json")
setAuthorizationHeader(httpReq, c.token)

resp, err := c.httpClient.Do(httpReq)
if err != nil {
return types.AppConfig{}, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return types.AppConfig{}, errorFromResponse(resp)
}

var config types.AppConfig
err = json.NewDecoder(resp.Body).Decode(&config)
if err != nil {
return types.AppConfig{}, err
}

return config, nil
}
16 changes: 11 additions & 5 deletions api/controllers/kubernetes/install/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (c *InstallController) GetAppConfig(ctx context.Context) (kotsv1beta1.Confi
return c.appConfigManager.GetConfig(*c.releaseData.AppConfig)
}

func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
func (c *InstallController) PatchAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
if c.releaseData == nil || c.releaseData.AppConfig == nil {
return errors.New("app config not found")
}
Expand Down Expand Up @@ -51,9 +51,9 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
}
}()

err = c.appConfigManager.SetConfigValues(*c.releaseData.AppConfig, values)
err = c.appConfigManager.PatchConfigValues(ctx, *c.releaseData.AppConfig, values)
if err != nil {
return fmt.Errorf("set app config values: %w", err)
return fmt.Errorf("patch app config values: %w", err)
}

err = c.stateMachine.Transition(lock, StateApplicationConfigured)
Expand All @@ -64,6 +64,12 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
return nil
}

func (c *InstallController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
return c.appConfigManager.GetConfigValues()
func (c *InstallController) GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error) {
// Get the app config to determine which fields are password type
appConfig, err := c.GetAppConfig(ctx)
if err != nil {
return nil, fmt.Errorf("get app config: %w", err)
}

return c.appConfigManager.GetConfigValues(ctx, appConfig, maskPasswords)
}
4 changes: 2 additions & 2 deletions api/controllers/kubernetes/install/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type Controller interface {
SetupInfra(ctx context.Context) error
GetInfra(ctx context.Context) (types.Infra, error)
GetAppConfig(ctx context.Context) (kotsv1beta1.Config, error)
SetAppConfigValues(ctx context.Context, values map[string]string) error
GetAppConfigValues(ctx context.Context) (map[string]string, error)
PatchAppConfigValues(ctx context.Context, values map[string]string) error
GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error)
}

var _ Controller = (*InstallController)(nil)
Expand Down
8 changes: 4 additions & 4 deletions api/controllers/kubernetes/install/controller_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ func (m *MockController) GetAppConfig(ctx context.Context) (kotsv1beta1.Config,
return args.Get(0).(kotsv1beta1.Config), args.Error(1)
}

// SetAppConfigValues mocks the SetAppConfigValues method
func (m *MockController) SetAppConfigValues(ctx context.Context, values map[string]string) error {
// PatchAppConfigValues mocks the PatchAppConfigValues method
func (m *MockController) PatchAppConfigValues(ctx context.Context, values map[string]string) error {
args := m.Called(ctx, values)
return args.Error(0)
}

// GetAppConfigValues mocks the GetAppConfigValues method
func (m *MockController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
args := m.Called(ctx)
func (m *MockController) GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error) {
args := m.Called(ctx, maskPasswords)
if args.Get(0) == nil {
return nil, args.Error(1)
}
Expand Down
2 changes: 1 addition & 1 deletion api/controllers/kubernetes/install/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (c *InstallController) SetupInfra(ctx context.Context) (finalErr error) {
}
}()

configValues, err := c.appConfigManager.GetKotsadmConfigValues(*c.releaseData.AppConfig)
configValues, err := c.appConfigManager.GetKotsadmConfigValues(ctx, *c.releaseData.AppConfig)
if err != nil {
return fmt.Errorf("failed to get kotsadm config values: %w", err)
}
Expand Down
16 changes: 11 additions & 5 deletions api/controllers/linux/install/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (c *InstallController) GetAppConfig(ctx context.Context) (kotsv1beta1.Confi
return c.appConfigManager.GetConfig(*c.releaseData.AppConfig)
}

func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
func (c *InstallController) PatchAppConfigValues(ctx context.Context, values map[string]string) (finalErr error) {
if c.releaseData == nil || c.releaseData.AppConfig == nil {
return errors.New("app config not found")
}
Expand Down Expand Up @@ -51,9 +51,9 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
}
}()

err = c.appConfigManager.SetConfigValues(*c.releaseData.AppConfig, values)
err = c.appConfigManager.PatchConfigValues(ctx, *c.releaseData.AppConfig, values)
if err != nil {
return fmt.Errorf("set app config values: %w", err)
return fmt.Errorf("patch app config values: %w", err)
}

err = c.stateMachine.Transition(lock, StateApplicationConfigured)
Expand All @@ -64,6 +64,12 @@ func (c *InstallController) SetAppConfigValues(ctx context.Context, values map[s
return nil
}

func (c *InstallController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
return c.appConfigManager.GetConfigValues()
func (c *InstallController) GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error) {
// Get the app config to determine which fields are password type
appConfig, err := c.GetAppConfig(ctx)
if err != nil {
return nil, fmt.Errorf("get app config: %w", err)
}

return c.appConfigManager.GetConfigValues(ctx, appConfig, maskPasswords)
}
4 changes: 2 additions & 2 deletions api/controllers/linux/install/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ type Controller interface {
SetupInfra(ctx context.Context, ignoreHostPreflights bool) error
GetInfra(ctx context.Context) (types.Infra, error)
GetAppConfig(ctx context.Context) (kotsv1beta1.Config, error)
SetAppConfigValues(ctx context.Context, values map[string]string) error
GetAppConfigValues(ctx context.Context) (map[string]string, error)
PatchAppConfigValues(ctx context.Context, values map[string]string) error
GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error)
}

type RunHostPreflightsOptions struct {
Expand Down
8 changes: 4 additions & 4 deletions api/controllers/linux/install/controller_mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ func (m *MockController) GetAppConfig(ctx context.Context) (kotsv1beta1.Config,
return args.Get(0).(kotsv1beta1.Config), args.Error(1)
}

// SetAppConfigValues mocks the SetAppConfigValues method
func (m *MockController) SetAppConfigValues(ctx context.Context, values map[string]string) error {
// PatchAppConfigValues mocks the PatchAppConfigValues method
func (m *MockController) PatchAppConfigValues(ctx context.Context, values map[string]string) error {
args := m.Called(ctx, values)
return args.Error(0)
}

// GetAppConfigValues mocks the GetAppConfigValues method
func (m *MockController) GetAppConfigValues(ctx context.Context) (map[string]string, error) {
args := m.Called(ctx)
func (m *MockController) GetAppConfigValues(ctx context.Context, maskPasswords bool) (map[string]string, error) {
args := m.Called(ctx, maskPasswords)
if args.Get(0) == nil {
return nil, args.Error(1)
}
Expand Down
2 changes: 1 addition & 1 deletion api/controllers/linux/install/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (c *InstallController) SetupInfra(ctx context.Context, ignoreHostPreflights
}
}

configValues, err := c.appConfigManager.GetKotsadmConfigValues(*c.releaseData.AppConfig)
configValues, err := c.appConfigManager.GetKotsadmConfigValues(ctx, *c.releaseData.AppConfig)
if err != nil {
return fmt.Errorf("failed to get kotsadm config values: %w", err)
}
Expand Down
Loading
Loading