Skip to content

Commit 4fe6332

Browse files
authored
API to get Config from release (#2421)
* API to get Config from release * update tests * feedback * f * f
1 parent 62a4a28 commit 4fe6332

File tree

22 files changed

+1563
-13
lines changed

22 files changed

+1563
-13
lines changed

api/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ include ../common.mk
55
.PHONY: swagger
66
swagger: swag
77
swag fmt -g api.go
8-
swag init --v3.1 -g api.go
8+
swag init --parseDependency --v3.1 -g api.go
99

1010
.PHONY: swag
1111
swag:

api/client/client.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88

99
"github.com/replicatedhq/embedded-cluster/api/types"
10+
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
1011
)
1112

1213
type Client interface {
@@ -16,12 +17,14 @@ type Client interface {
1617
ConfigureLinuxInstallation(config types.LinuxInstallationConfig) (types.Status, error)
1718
SetupLinuxInfra(ignoreHostPreflights bool) (types.Infra, error)
1819
GetLinuxInfraStatus() (types.Infra, error)
20+
GetLinuxAppConfig() (kotsv1beta1.Config, error)
1921

2022
GetKubernetesInstallationConfig() (types.KubernetesInstallationConfig, error)
2123
ConfigureKubernetesInstallation(config types.KubernetesInstallationConfig) (types.Status, error)
2224
GetKubernetesInstallationStatus() (types.Status, error)
2325
SetupKubernetesInfra() (types.Infra, error)
2426
GetKubernetesInfraStatus() (types.Infra, error)
27+
GetKubernetesAppConfig() (kotsv1beta1.Config, error)
2528
}
2629

2730
type client struct {

api/client/client_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"testing"
1010

1111
"github.com/replicatedhq/embedded-cluster/api/types"
12+
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
13+
"github.com/replicatedhq/kotskinds/multitype"
1214
"github.com/stretchr/testify/assert"
1315
"github.com/stretchr/testify/require"
1416
)
@@ -582,3 +584,129 @@ func TestErrorFromResponse(t *testing.T) {
582584
assert.Error(t, err)
583585
assert.Contains(t, err.Error(), "unexpected response")
584586
}
587+
588+
func TestLinuxGetAppConfig(t *testing.T) {
589+
// Define expected config once
590+
expectedConfig := kotsv1beta1.Config{
591+
Spec: kotsv1beta1.ConfigSpec{
592+
Groups: []kotsv1beta1.ConfigGroup{
593+
{
594+
Name: "test-group",
595+
Title: "Test Group",
596+
Items: []kotsv1beta1.ConfigItem{
597+
{
598+
Name: "test-item",
599+
Type: "text",
600+
Title: "Test Item",
601+
Default: multitype.BoolOrString{StrVal: "default"},
602+
Value: multitype.BoolOrString{StrVal: "value"},
603+
},
604+
},
605+
},
606+
},
607+
},
608+
}
609+
610+
// Create a test server
611+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
612+
assert.Equal(t, "GET", r.Method)
613+
assert.Equal(t, "/api/linux/install/app/config", r.URL.Path)
614+
615+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
616+
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
617+
618+
// Return successful response
619+
w.WriteHeader(http.StatusOK)
620+
json.NewEncoder(w).Encode(expectedConfig)
621+
}))
622+
defer server.Close()
623+
624+
// Test successful get
625+
c := New(server.URL, WithToken("test-token"))
626+
config, err := c.GetLinuxAppConfig()
627+
assert.NoError(t, err)
628+
assert.Equal(t, expectedConfig, config)
629+
630+
// Test error response
631+
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
632+
w.WriteHeader(http.StatusInternalServerError)
633+
json.NewEncoder(w).Encode(types.APIError{
634+
StatusCode: http.StatusInternalServerError,
635+
Message: "Internal Server Error",
636+
})
637+
}))
638+
defer errorServer.Close()
639+
640+
c = New(errorServer.URL, WithToken("test-token"))
641+
config, err = c.GetLinuxAppConfig()
642+
assert.Error(t, err)
643+
assert.Equal(t, kotsv1beta1.Config{}, config)
644+
645+
apiErr, ok := err.(*types.APIError)
646+
require.True(t, ok, "Expected err to be of type *types.APIError")
647+
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
648+
assert.Equal(t, "Internal Server Error", apiErr.Message)
649+
}
650+
651+
func TestKubernetesGetAppConfig(t *testing.T) {
652+
// Define expected config once
653+
expectedConfig := kotsv1beta1.Config{
654+
Spec: kotsv1beta1.ConfigSpec{
655+
Groups: []kotsv1beta1.ConfigGroup{
656+
{
657+
Name: "test-group",
658+
Title: "Test Group",
659+
Items: []kotsv1beta1.ConfigItem{
660+
{
661+
Name: "test-item",
662+
Type: "text",
663+
Title: "Test Item",
664+
Default: multitype.BoolOrString{StrVal: "default"},
665+
Value: multitype.BoolOrString{StrVal: "value"},
666+
},
667+
},
668+
},
669+
},
670+
},
671+
}
672+
673+
// Create a test server
674+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
675+
assert.Equal(t, "GET", r.Method)
676+
assert.Equal(t, "/api/kubernetes/install/app/config", r.URL.Path)
677+
678+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
679+
assert.Equal(t, "Bearer test-token", r.Header.Get("Authorization"))
680+
681+
// Return successful response
682+
w.WriteHeader(http.StatusOK)
683+
json.NewEncoder(w).Encode(expectedConfig)
684+
}))
685+
defer server.Close()
686+
687+
// Test successful get
688+
c := New(server.URL, WithToken("test-token"))
689+
config, err := c.GetKubernetesAppConfig()
690+
assert.NoError(t, err)
691+
assert.Equal(t, expectedConfig, config)
692+
693+
// Test error response
694+
errorServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
695+
w.WriteHeader(http.StatusInternalServerError)
696+
json.NewEncoder(w).Encode(types.APIError{
697+
StatusCode: http.StatusInternalServerError,
698+
Message: "Internal Server Error",
699+
})
700+
}))
701+
defer errorServer.Close()
702+
703+
c = New(errorServer.URL, WithToken("test-token"))
704+
config, err = c.GetKubernetesAppConfig()
705+
assert.Error(t, err)
706+
assert.Equal(t, kotsv1beta1.Config{}, config)
707+
708+
apiErr, ok := err.(*types.APIError)
709+
require.True(t, ok, "Expected err to be of type *types.APIError")
710+
assert.Equal(t, http.StatusInternalServerError, apiErr.StatusCode)
711+
assert.Equal(t, "Internal Server Error", apiErr.Message)
712+
}

api/client/install.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net/http"
77

88
"github.com/replicatedhq/embedded-cluster/api/types"
9+
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
910
)
1011

1112
func (c *client) GetLinuxInstallationConfig() (types.LinuxInstallationConfig, error) {
@@ -294,3 +295,57 @@ func (c *client) GetKubernetesInfraStatus() (types.Infra, error) {
294295

295296
return infra, nil
296297
}
298+
299+
func (c *client) GetLinuxAppConfig() (kotsv1beta1.Config, error) {
300+
req, err := http.NewRequest("GET", c.apiURL+"/api/linux/install/app/config", nil)
301+
if err != nil {
302+
return kotsv1beta1.Config{}, err
303+
}
304+
req.Header.Set("Content-Type", "application/json")
305+
setAuthorizationHeader(req, c.token)
306+
307+
resp, err := c.httpClient.Do(req)
308+
if err != nil {
309+
return kotsv1beta1.Config{}, err
310+
}
311+
defer resp.Body.Close()
312+
313+
if resp.StatusCode != http.StatusOK {
314+
return kotsv1beta1.Config{}, errorFromResponse(resp)
315+
}
316+
317+
var config kotsv1beta1.Config
318+
err = json.NewDecoder(resp.Body).Decode(&config)
319+
if err != nil {
320+
return kotsv1beta1.Config{}, err
321+
}
322+
323+
return config, nil
324+
}
325+
326+
func (c *client) GetKubernetesAppConfig() (kotsv1beta1.Config, error) {
327+
req, err := http.NewRequest("GET", c.apiURL+"/api/kubernetes/install/app/config", nil)
328+
if err != nil {
329+
return kotsv1beta1.Config{}, err
330+
}
331+
req.Header.Set("Content-Type", "application/json")
332+
setAuthorizationHeader(req, c.token)
333+
334+
resp, err := c.httpClient.Do(req)
335+
if err != nil {
336+
return kotsv1beta1.Config{}, err
337+
}
338+
defer resp.Body.Close()
339+
340+
if resp.StatusCode != http.StatusOK {
341+
return kotsv1beta1.Config{}, errorFromResponse(resp)
342+
}
343+
344+
var config kotsv1beta1.Config
345+
err = json.NewDecoder(resp.Body).Decode(&config)
346+
if err != nil {
347+
return kotsv1beta1.Config{}, err
348+
}
349+
350+
return config, nil
351+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package install
2+
3+
import (
4+
"context"
5+
6+
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
7+
)
8+
9+
func (c *InstallController) GetAppConfig(ctx context.Context) (kotsv1beta1.Config, error) {
10+
return c.appConfigManager.Get()
11+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package install
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/replicatedhq/embedded-cluster/pkg/release"
8+
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
9+
"github.com/replicatedhq/kotskinds/multitype"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
func TestInstallController_GetAppConfig(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
releaseData *release.ReleaseData
18+
expectedConfig kotsv1beta1.Config
19+
expectedError bool
20+
}{
21+
{
22+
name: "successful get app config",
23+
releaseData: &release.ReleaseData{
24+
AppConfig: &kotsv1beta1.Config{
25+
Spec: kotsv1beta1.ConfigSpec{
26+
Groups: []kotsv1beta1.ConfigGroup{
27+
{
28+
Name: "test-group",
29+
Title: "Test Group",
30+
Items: []kotsv1beta1.ConfigItem{
31+
{
32+
Name: "test-item",
33+
Type: "text",
34+
Title: "Test Item",
35+
Default: multitype.BoolOrString{StrVal: "default"},
36+
Value: multitype.BoolOrString{StrVal: "value"},
37+
},
38+
},
39+
},
40+
},
41+
},
42+
},
43+
},
44+
expectedConfig: kotsv1beta1.Config{
45+
Spec: kotsv1beta1.ConfigSpec{
46+
Groups: []kotsv1beta1.ConfigGroup{
47+
{
48+
Name: "test-group",
49+
Title: "Test Group",
50+
Items: []kotsv1beta1.ConfigItem{
51+
{
52+
Name: "test-item",
53+
Type: "text",
54+
Title: "Test Item",
55+
Default: multitype.BoolOrString{StrVal: "default"},
56+
Value: multitype.BoolOrString{StrVal: "value"},
57+
},
58+
},
59+
},
60+
},
61+
},
62+
},
63+
expectedError: false,
64+
},
65+
{
66+
name: "empty config",
67+
releaseData: &release.ReleaseData{
68+
AppConfig: &kotsv1beta1.Config{
69+
Spec: kotsv1beta1.ConfigSpec{},
70+
},
71+
},
72+
expectedConfig: kotsv1beta1.Config{
73+
Spec: kotsv1beta1.ConfigSpec{},
74+
},
75+
expectedError: false,
76+
},
77+
{
78+
name: "nil release data",
79+
releaseData: nil,
80+
expectedConfig: kotsv1beta1.Config{},
81+
expectedError: false,
82+
},
83+
{
84+
name: "nil app config",
85+
releaseData: &release.ReleaseData{
86+
AppConfig: nil,
87+
},
88+
expectedConfig: kotsv1beta1.Config{},
89+
expectedError: false,
90+
},
91+
}
92+
93+
for _, tt := range tests {
94+
t.Run(tt.name, func(t *testing.T) {
95+
// Create controller using NewInstallController with release data
96+
controller, err := NewInstallController(
97+
WithReleaseData(tt.releaseData),
98+
)
99+
require.NoError(t, err)
100+
101+
config, err := controller.GetAppConfig(context.Background())
102+
103+
if tt.expectedError {
104+
assert.Error(t, err)
105+
assert.Equal(t, kotsv1beta1.Config{}, config)
106+
} else {
107+
assert.NoError(t, err)
108+
assert.Equal(t, tt.expectedConfig, config)
109+
}
110+
})
111+
}
112+
}

0 commit comments

Comments
 (0)