Skip to content

Commit f21434a

Browse files
authored
Export import server config from settings page (#2664)
1 parent 6c0e7ba commit f21434a

20 files changed

+1397
-22
lines changed

integration/admin_api_integration_test.go

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@ import (
2222
"bytes"
2323
"encoding/json"
2424
"fmt"
25+
"io"
2526
"log"
27+
"mime/multipart"
2628
"net/http"
29+
"os"
30+
"path"
2731
"testing"
2832
"time"
2933

@@ -155,33 +159,33 @@ func NotifyPostgres() (*http.Response, error) {
155159

156160
func TestNotifyPostgres(t *testing.T) {
157161
// Variables
158-
assert := assert.New(t)
162+
asserter := assert.New(t)
159163

160164
// Test
161165
response, err := NotifyPostgres()
162166
finalResponse := inspectHTTPResponse(response)
163-
assert.Nil(err)
167+
asserter.Nil(err)
164168
if err != nil {
165169
log.Println(err)
166-
assert.Fail(finalResponse)
170+
asserter.Fail(finalResponse)
167171
return
168172
}
169173
if response != nil {
170-
assert.Equal(200, response.StatusCode, finalResponse)
174+
asserter.Equal(200, response.StatusCode, finalResponse)
171175
}
172176
}
173177

174178
func TestRestartService(t *testing.T) {
175-
assert := assert.New(t)
179+
asserter := assert.New(t)
176180
restartResponse, restartError := RestartService()
177-
assert.Nil(restartError)
181+
asserter.Nil(restartError)
178182
if restartError != nil {
179183
log.Println(restartError)
180184
return
181185
}
182186
addObjRsp := inspectHTTPResponse(restartResponse)
183187
if restartResponse != nil {
184-
assert.Equal(
188+
asserter.Equal(
185189
204,
186190
restartResponse.StatusCode,
187191
addObjRsp,
@@ -212,18 +216,18 @@ func ListPoliciesWithBucket(bucketName string) (*http.Response, error) {
212216
func TestListPoliciesWithBucket(t *testing.T) {
213217
// Test Variables
214218
bucketName := "testlistpolicieswithbucket"
215-
assert := assert.New(t)
219+
asserter := assert.New(t)
216220

217221
// Test
218222
response, err := ListPoliciesWithBucket(bucketName)
219-
assert.Nil(err)
223+
asserter.Nil(err)
220224
if err != nil {
221225
log.Println(err)
222226
return
223227
}
224228
parsedResponse := inspectHTTPResponse(response)
225229
if response != nil {
226-
assert.Equal(
230+
asserter.Equal(
227231
200,
228232
response.StatusCode,
229233
parsedResponse,
@@ -254,18 +258,18 @@ func ListUsersWithAccessToBucket(bucketName string) (*http.Response, error) {
254258
func TestListUsersWithAccessToBucket(t *testing.T) {
255259
// Test Variables
256260
bucketName := "testlistuserswithaccesstobucket1"
257-
assert := assert.New(t)
261+
asserter := assert.New(t)
258262

259263
// Test
260264
response, err := ListUsersWithAccessToBucket(bucketName)
261-
assert.Nil(err)
265+
asserter.Nil(err)
262266
if err != nil {
263267
log.Println(err)
264268
return
265269
}
266270
parsedResponse := inspectHTTPResponse(response)
267271
if response != nil {
268-
assert.Equal(
272+
asserter.Equal(
269273
200,
270274
response.StatusCode,
271275
parsedResponse,
@@ -274,16 +278,16 @@ func TestListUsersWithAccessToBucket(t *testing.T) {
274278
}
275279

276280
func TestGetNodes(t *testing.T) {
277-
assert := assert.New(t)
281+
asserter := assert.New(t)
278282
getNodesResponse, getNodesError := GetNodes()
279-
assert.Nil(getNodesError)
283+
asserter.Nil(getNodesError)
280284
if getNodesError != nil {
281285
log.Println(getNodesError)
282286
return
283287
}
284288
addObjRsp := inspectHTTPResponse(getNodesResponse)
285289
if getNodesResponse != nil {
286-
assert.Equal(
290+
asserter.Equal(
287291
200,
288292
getNodesResponse.StatusCode,
289293
addObjRsp,
@@ -312,16 +316,89 @@ func ArnList() (*http.Response, error) {
312316
}
313317

314318
func TestArnList(t *testing.T) {
315-
assert := assert.New(t)
319+
asserter := assert.New(t)
316320
resp, err := ArnList()
317-
assert.Nil(err)
321+
asserter.Nil(err)
318322
if err != nil {
319323
log.Println(err)
320324
return
321325
}
322326
objRsp := inspectHTTPResponse(resp)
323327
if resp != nil {
324-
assert.Equal(
328+
asserter.Equal(
329+
200,
330+
resp.StatusCode,
331+
objRsp,
332+
)
333+
}
334+
}
335+
336+
func ExportConfig() (*http.Response, error) {
337+
request, err := http.NewRequest(
338+
"GET", "http://localhost:9090/api/v1/configs/export", nil)
339+
if err != nil {
340+
log.Println(err)
341+
}
342+
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
343+
client := &http.Client{
344+
Timeout: 2 * time.Second,
345+
}
346+
response, err := client.Do(request)
347+
return response, err
348+
}
349+
350+
func ImportConfig() (*http.Response, error) {
351+
body := &bytes.Buffer{}
352+
writer := multipart.NewWriter(body)
353+
formFile, _ := writer.CreateFormFile("file", "sample-import-config.txt")
354+
fileDir, _ := os.Getwd()
355+
fileName := "sample-import-config.txt"
356+
filePath := path.Join(fileDir, fileName)
357+
file, _ := os.Open(filePath)
358+
io.Copy(formFile, file)
359+
writer.Close()
360+
request, err := http.NewRequest(
361+
"POST", "http://localhost:9090/api/v1/configs/import",
362+
bytes.NewReader(body.Bytes()),
363+
)
364+
if err != nil {
365+
log.Println(err)
366+
}
367+
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
368+
request.Header.Set("Content-Type", writer.FormDataContentType())
369+
370+
client := &http.Client{
371+
Timeout: 2 * time.Second,
372+
}
373+
374+
rsp, _ := client.Do(request)
375+
if rsp.StatusCode != http.StatusOK {
376+
log.Printf("Request failed with response code: %d", rsp.StatusCode)
377+
}
378+
return rsp, err
379+
}
380+
381+
func TestExportConfig(t *testing.T) {
382+
asserter := assert.New(t)
383+
resp, err := ExportConfig()
384+
asserter.Nil(err)
385+
objRsp := inspectHTTPResponse(resp)
386+
if resp != nil {
387+
asserter.Equal(
388+
200,
389+
resp.StatusCode,
390+
objRsp,
391+
)
392+
}
393+
}
394+
395+
func TestImportConfig(t *testing.T) {
396+
asserter := assert.New(t)
397+
resp, err := ImportConfig()
398+
asserter.Nil(err)
399+
objRsp := inspectHTTPResponse(resp)
400+
if resp != nil {
401+
asserter.Equal(
325402
200,
326403
resp.StatusCode,
327404
objRsp,

integration/sample-import-config.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
subnet license= api_key= proxy=
2+
# callhome enable=off frequency=24h
3+
# site name= region=
4+
# api requests_max=0 requests_deadline=10s cluster_deadline=10s cors_allow_origin=* remote_transport_deadline=2h list_quorum=strict replication_priority=auto transition_workers=100 stale_uploads_cleanup_interval=6h stale_uploads_expiry=24h delete_cleanup_interval=5m disable_odirect=off gzip_objects=off
5+
# scanner speed=default
6+
# compression enable=off allow_encryption=off extensions=.txt,.log,.csv,.json,.tar,.xml,.bin mime_types=text/*,application/json,application/xml,binary/octet-stream
7+
# identity_openid enable= display_name= config_url= client_id= client_secret= claim_name=policy claim_userinfo= role_policy= claim_prefix= redirect_uri= redirect_uri_dynamic=off scopes= vendor= keycloak_realm= keycloak_admin_url=
8+
# identity_ldap server_addr= srv_record_name= user_dn_search_base_dn= user_dn_search_filter= group_search_filter= group_search_base_dn= tls_skip_verify=off server_insecure=off server_starttls=off lookup_bind_dn= lookup_bind_password=
9+
# identity_tls skip_verify=off
10+
# identity_plugin url= auth_token= role_policy= role_id=
11+
# policy_plugin url= auth_token= enable_http2=off
12+
# logger_webhook enable=off endpoint= auth_token= client_cert= client_key= queue_size=100000
13+
# audit_webhook enable=off endpoint= auth_token= client_cert= client_key= queue_size=100000
14+
# audit_kafka enable=off topic= brokers= sasl_username= sasl_password= sasl_mechanism=plain client_tls_cert= client_tls_key= tls_client_auth=0 sasl=off tls=off tls_skip_verify=off version=
15+
# notify_webhook enable=off endpoint= auth_token= queue_limit=0 queue_dir= client_cert= client_key=
16+
# notify_amqp enable=off url= exchange= exchange_type= routing_key= mandatory=off durable=off no_wait=off internal=off auto_deleted=off delivery_mode=0 publisher_confirms=off queue_limit=0 queue_dir=
17+
# notify_kafka enable=off topic= brokers= sasl_username= sasl_password= sasl_mechanism=plain client_tls_cert= client_tls_key= tls_client_auth=0 sasl=off tls=off tls_skip_verify=off queue_limit=0 queue_dir= version=
18+
# notify_mqtt enable=off broker= topic= password= username= qos=0 keep_alive_interval=0s reconnect_interval=0s queue_dir= queue_limit=0
19+
# notify_nats enable=off address= subject= username= password= token= tls=off tls_skip_verify=off cert_authority= client_cert= client_key= ping_interval=0 jetstream=off streaming=off streaming_async=off streaming_max_pub_acks_in_flight=0 streaming_cluster_id= queue_dir= queue_limit=0
20+
# notify_nsq enable=off nsqd_address= topic= tls=off tls_skip_verify=off queue_dir= queue_limit=0
21+
# notify_mysql enable=off format=namespace dsn_string= table= queue_dir= queue_limit=0 max_open_connections=2
22+
# notify_postgres enable=off format=namespace connection_string= table= queue_dir= queue_limit=0 max_open_connections=2
23+
# notify_elasticsearch enable=off url= format=namespace index= queue_dir= queue_limit=0 username= password=
24+
# notify_redis enable=off format=namespace address= key= password= queue_dir= queue_limit=0
25+
# etcd endpoints= path_prefix= coredns_path=/skydns client_cert= client_cert_key=
26+
# cache drives= exclude= expiry=90 quota=80 after=0 watermark_low=70 watermark_high=80 range=on commit=
27+
# storage_class standard= rrs=EC:1
28+
# heal bitrotscan=off max_sleep=1s max_io=100

models/config_export_response.go

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

models/env_override.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

portal-ui/src/screens/Console/Common/Hooks/useApi.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ const useApi = (
1212
): [IsApiInProgress, ApiMethodToInvoke] => {
1313
const [isLoading, setIsLoading] = useState<boolean>(false);
1414

15-
const callApi = (method: string, url: string, data?: any) => {
15+
const callApi = (method: string, url: string, data?: any, headers?: any) => {
1616
setIsLoading(true);
1717
api
18-
.invoke(method, url, data)
18+
.invoke(method, url, data, headers)
1919
.then((res: any) => {
2020
setIsLoading(false);
2121
onSuccess(res);

portal-ui/src/screens/Console/Configurations/ConfigurationPanels/ConfigurationOptions.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
3434
import ConfigurationForm from "./ConfigurationForm";
3535
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
3636
import PageHeaderWrapper from "../../Common/PageHeaderWrapper/PageHeaderWrapper";
37+
import ExportConfigButton from "./ExportConfigButton";
38+
import ImportConfigButton from "./ImportConfigButton";
39+
import { Box } from "@mui/material";
3740

3841
interface IConfigurationOptions {
3942
classes: any;
@@ -78,6 +81,17 @@ const ConfigurationOptions = ({ classes }: IConfigurationOptions) => {
7881
<ScreenTitle
7982
icon={<SettingsIcon />}
8083
title={"MinIO Configuration:"}
84+
actions={
85+
<Box
86+
sx={{
87+
display: "flex",
88+
gap: 2,
89+
}}
90+
>
91+
<ImportConfigButton />
92+
<ExportConfigButton />
93+
</Box>
94+
}
8195
/>
8296
<VerticalTabs
8397
selectedTab={selConfigTab}

0 commit comments

Comments
 (0)