Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aa5081889 | ||
|
|
9c5d4aaf11 | ||
|
|
04adf25e65 | ||
|
|
8f77261872 | ||
|
|
8b7505c466 | ||
|
|
b420ef3c1f | ||
|
|
e235863b94 | ||
|
|
6b7948b6cd | ||
|
|
87c373b08c | ||
|
|
9844269c1a | ||
|
|
6866b84da8 | ||
|
|
5b19fb3d96 | ||
|
|
fce2a148b8 | ||
|
|
69e1d653ce | ||
|
|
9b88dd6348 | ||
|
|
85c0e5eca2 | ||
|
|
17684f37d9 | ||
|
|
175b87c355 | ||
|
|
5fff9ebfd4 | ||
|
|
795497a60d | ||
|
|
48119acc72 | ||
|
|
ddb23ea1c8 | ||
|
|
6ec7ec3c25 | ||
|
|
39d3690ac0 | ||
|
|
41e0fce068 | ||
|
|
d876bebf28 | ||
|
|
7cb04ce62b | ||
|
|
326d709bf9 | ||
|
|
40dcc9eb33 | ||
|
|
b8f024aa39 |
8
.github/workflows/console-sa-secret.yaml
vendored
Normal file
8
.github/workflows/console-sa-secret.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: console-sa-secret
|
||||
namespace: minio-operator
|
||||
annotations:
|
||||
kubernetes.io/service-account.name: console-sa
|
||||
type: kubernetes.io/service-account-token
|
||||
53
.github/workflows/deploy-tenant.sh
vendored
53
.github/workflows/deploy-tenant.sh
vendored
@@ -20,17 +20,17 @@ export SCRIPT_DIR
|
||||
|
||||
source "${SCRIPT_DIR}/common.sh"
|
||||
|
||||
function install_tenants() {
|
||||
echo "Installing tenants"
|
||||
|
||||
# Install lite & kes tenants
|
||||
try kubectl apply -k "${SCRIPT_DIR}/../../portal-ui/tests/scripts/tenant-lite"
|
||||
try kubectl apply -k "${SCRIPT_DIR}/../../portal-ui/tests/scripts/tenant-kes-encryption"
|
||||
|
||||
function install_tenant() {
|
||||
echo "Installing lite tenant"
|
||||
|
||||
try kubectl apply -k "${SCRIPT_DIR}/../../portal-ui/tests/scripts/tenant"
|
||||
|
||||
echo "Waiting for the tenant statefulset, this indicates the tenant is being fulfilled"
|
||||
waitdone=0
|
||||
totalwait=0
|
||||
while true; do
|
||||
echo "Waiting for the tenant statefulset, this indicates the tenant is being fulfilled"
|
||||
waitdone=0
|
||||
totalwait=0
|
||||
while true; do
|
||||
waitdone=$(kubectl -n tenant-lite get pods -l v1.min.io/tenant=storage-lite --no-headers | wc -l)
|
||||
if [ "$waitdone" -ne 0 ]; then
|
||||
echo "Found $waitdone pods"
|
||||
@@ -39,33 +39,34 @@ function install_tenant() {
|
||||
sleep 5
|
||||
totalwait=$((totalwait + 5))
|
||||
if [ "$totalwait" -gt 300 ]; then
|
||||
echo "Tenant never created statefulset after 5 minutes"
|
||||
try false
|
||||
echo "Tenant never created statefulset after 5 minutes"
|
||||
try false
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
echo "Waiting for tenant pods to come online (5m timeout)"
|
||||
try kubectl wait --namespace tenant-lite \
|
||||
echo "Waiting for tenant pods to come online (5m timeout)"
|
||||
try kubectl wait --namespace tenant-lite \
|
||||
--for=condition=ready pod \
|
||||
--selector="v1.min.io/tenant=storage-lite" \
|
||||
--timeout=300s
|
||||
|
||||
echo "Build passes basic tenant creation"
|
||||
echo "Build passes basic tenant creation"
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
destroy_kind
|
||||
|
||||
setup_kind
|
||||
|
||||
install_operator
|
||||
|
||||
install_tenant
|
||||
|
||||
check_tenant_status tenant-lite storage-lite
|
||||
|
||||
kubectl proxy &
|
||||
destroy_kind
|
||||
setup_kind
|
||||
install_operator
|
||||
install_tenants
|
||||
check_tenant_status tenant-lite storage-lite
|
||||
kubectl proxy &
|
||||
# Beginning Kubernetes 1.24 ----> Service Account Token Secrets are not
|
||||
# automatically generated, to generate them manually, users must manually
|
||||
# create the secret, for our examples where we lead people to get the JWT
|
||||
# from the console-sa service account, they additionally need to manually
|
||||
# generate the secret via
|
||||
kubectl apply -f "${SCRIPT_DIR}/console-sa-secret.yaml"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
128
.github/workflows/jobs.yaml
vendored
128
.github/workflows/jobs.yaml
vendored
@@ -808,6 +808,75 @@ jobs:
|
||||
with:
|
||||
args: '"chrome:headless" portal-ui/tests/permissions-6/ --skip-js-errors'
|
||||
|
||||
all-permissions-7:
|
||||
name: Permissions Tests Part 7
|
||||
needs:
|
||||
- lint-job
|
||||
- no-warnings-and-make-assets
|
||||
- reuse-golang-dependencies
|
||||
- vulnerable-dependencies-checks
|
||||
- semgrep-static-code-analysis
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.17.x ]
|
||||
os: [ ubuntu-latest ]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
id: go
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
name: Yarn Cache
|
||||
with:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
./portal-ui/node_modules/
|
||||
./portal-ui/build/
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('./portal-ui/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
- uses: actions/cache@v2
|
||||
id: assets-cache
|
||||
name: Assets Cache
|
||||
with:
|
||||
path: |
|
||||
./portal-ui/build/
|
||||
key: ${{ runner.os }}-assets-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-assets-
|
||||
- uses: actions/cache@v2
|
||||
name: Go Mod Cache
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
- name: Build Console on ${{ matrix.os }}
|
||||
env:
|
||||
GO111MODULE: on
|
||||
GOOS: linux
|
||||
run: |
|
||||
make console
|
||||
- name: Start Console, front-end app and initialize users/policies
|
||||
run: |
|
||||
(./console server) & (make initialize-permissions)
|
||||
- name: Run TestCafe Tests
|
||||
timeout-minutes: 5
|
||||
uses: DevExpress/testcafe-action@latest
|
||||
with:
|
||||
args: '"chrome:headless" portal-ui/tests/permissions-7/ --skip-js-errors'
|
||||
|
||||
all-operator-tests:
|
||||
name: Operator UI Tests
|
||||
needs:
|
||||
@@ -1194,6 +1263,52 @@ jobs:
|
||||
./restapi/coverage/
|
||||
key: ${{ runner.os }}-coverage-restapi-2-${{ github.run_id }}
|
||||
|
||||
test-operatorapi-on-go:
|
||||
name: Test Operatorapi on Go ${{ matrix.go-version }} and ${{ matrix.os }}
|
||||
needs:
|
||||
- lint-job
|
||||
- no-warnings-and-make-assets
|
||||
- reuse-golang-dependencies
|
||||
- vulnerable-dependencies-checks
|
||||
- semgrep-static-code-analysis
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 1.17.x ]
|
||||
os: [ ubuntu-latest ]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/cache@v2
|
||||
name: Go Mod Cache
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ github.run_id }}
|
||||
|
||||
- name: Build on ${{ matrix.os }}
|
||||
env:
|
||||
GO111MODULE: on
|
||||
GOOS: linux
|
||||
run: |
|
||||
make test-unit-test-operator
|
||||
|
||||
- uses: actions/cache@v2
|
||||
id: coverage-cache-unittest-operatorapi
|
||||
name: Coverage Cache unit test operatorAPI
|
||||
with:
|
||||
path: |
|
||||
./operatorapi/coverage/
|
||||
key: ${{ runner.os }}-coverage-unittest-operatorapi-2-${{ github.run_id }}
|
||||
|
||||
b-integration-tests:
|
||||
name: Integration Tests with Latest Distributed MinIO
|
||||
needs:
|
||||
@@ -1286,6 +1401,7 @@ jobs:
|
||||
needs:
|
||||
- b-integration-tests
|
||||
- test-restapi-on-go
|
||||
- test-operatorapi-on-go
|
||||
- c-operator-api-tests
|
||||
- test-pkg-on-go
|
||||
- sso-integration
|
||||
@@ -1356,6 +1472,14 @@ jobs:
|
||||
./restapi/coverage/
|
||||
key: ${{ runner.os }}-coverage-restapi-2-${{ github.run_id }}
|
||||
|
||||
- uses: actions/cache@v2
|
||||
id: coverage-cache-unittest-operatorapi
|
||||
name: Coverage Cache unit test operatorAPI
|
||||
with:
|
||||
path: |
|
||||
./operatorapi/coverage/
|
||||
key: ${{ runner.os }}-coverage-unittest-operatorapi-2-${{ github.run_id }}
|
||||
|
||||
- uses: actions/cache@v2
|
||||
id: coverage-cache-pkg
|
||||
name: Coverage Cache Pkg
|
||||
@@ -1375,7 +1499,7 @@ jobs:
|
||||
echo "go build gocoverage.go"
|
||||
go build gocovmerge.go
|
||||
echo "put together the outs for final coverage resolution"
|
||||
./gocovmerge ../integration/coverage/system.out ../replication/coverage/replication.out ../sso-integration/coverage/sso-system.out ../restapi/coverage/coverage.out ../pkg/coverage/coverage-pkg.out ../operator-integration/coverage/operator-api.out > all.out
|
||||
./gocovmerge ../integration/coverage/system.out ../replication/coverage/replication.out ../sso-integration/coverage/sso-system.out ../restapi/coverage/coverage.out ../pkg/coverage/coverage-pkg.out ../operator-integration/coverage/operator-api.out ../operatorapi/coverage/coverage-unit-test-operatorapi.out > all.out
|
||||
echo "Download mc for Ubuntu"
|
||||
wget -q https://dl.min.io/client/mc/release/linux-amd64/mc
|
||||
echo "Change the permissions to execute mc command"
|
||||
@@ -1395,7 +1519,7 @@ jobs:
|
||||
go tool cover -func=all.out | grep total > tmp2
|
||||
result=`cat tmp2 | awk 'END {print $3}'`
|
||||
result=${result%\%}
|
||||
threshold=46.6
|
||||
threshold=50.5
|
||||
echo "Result:"
|
||||
echo "$result%"
|
||||
if (( $(echo "$result >= $threshold" |bc -l) )); then
|
||||
|
||||
24
Makefile
24
Makefile
@@ -202,6 +202,26 @@ test-permissions-3:
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-3/")
|
||||
@(docker stop minio)
|
||||
|
||||
test-permissions-4:
|
||||
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-4/")
|
||||
@(docker stop minio)
|
||||
|
||||
test-permissions-5:
|
||||
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-5/")
|
||||
@(docker stop minio)
|
||||
|
||||
test-permissions-6:
|
||||
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-6/")
|
||||
@(docker stop minio)
|
||||
|
||||
test-permissions-7:
|
||||
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-7/")
|
||||
@(docker stop minio)
|
||||
|
||||
test-apply-permissions:
|
||||
@(env bash $(PWD)/portal-ui/tests/scripts/initialize-env.sh)
|
||||
|
||||
@@ -222,6 +242,10 @@ test:
|
||||
@echo "execute test and get coverage"
|
||||
@(cd restapi && mkdir coverage && GO111MODULE=on go test -test.v -coverprofile=coverage/coverage.out)
|
||||
|
||||
test-unit-test-operator:
|
||||
@echo "execute unit test and get coverage for operatorapi"
|
||||
@(cd operatorapi && mkdir coverage && GO111MODULE=on go test -test.v -coverprofile=coverage/coverage-unit-test-operatorapi.out)
|
||||
|
||||
test-pkg:
|
||||
@echo "execute test and get coverage"
|
||||
@(cd pkg && mkdir coverage && GO111MODULE=on go test -test.v -coverprofile=coverage/coverage-pkg.out)
|
||||
|
||||
@@ -34,6 +34,7 @@ func Test_AddAccessRuleAPI(t *testing.T) {
|
||||
AddBucket("testaccessruleadd", false, false, nil, nil)
|
||||
|
||||
type args struct {
|
||||
bucket string
|
||||
prefix string
|
||||
access string
|
||||
}
|
||||
@@ -46,6 +47,7 @@ func Test_AddAccessRuleAPI(t *testing.T) {
|
||||
{
|
||||
name: "Create Access Rule - Valid",
|
||||
args: args{
|
||||
bucket: "testaccessruleadd",
|
||||
prefix: "/test/",
|
||||
access: "readonly",
|
||||
},
|
||||
@@ -53,14 +55,25 @@ func Test_AddAccessRuleAPI(t *testing.T) {
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Create Group - Invalid",
|
||||
name: "Add Access Rule - Invalid",
|
||||
args: args{
|
||||
bucket: "testaccessruleadd",
|
||||
prefix: "/test/",
|
||||
access: "readonl",
|
||||
},
|
||||
expectedStatus: 500,
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Add Access Rule - Invalid Bucket",
|
||||
args: args{
|
||||
bucket: "fakebucket",
|
||||
prefix: "/test/",
|
||||
access: "readonl",
|
||||
},
|
||||
expectedStatus: 404,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -76,7 +89,114 @@ func Test_AddAccessRuleAPI(t *testing.T) {
|
||||
requestDataJSON, _ := json.Marshal(requestDataPolicy)
|
||||
requestDataBody := bytes.NewReader(requestDataJSON)
|
||||
request, err := http.NewRequest(
|
||||
"PUT", "http://localhost:9090/api/v1/bucket/testaccessruleadd/access-rules", requestDataBody)
|
||||
"PUT", fmt.Sprintf("http://localhost:9090/api/v1/bucket/%s/access-rules", tt.args.bucket), requestDataBody)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
if response != nil {
|
||||
assert.Equal(tt.expectedStatus, response.StatusCode, "Status Code is incorrect")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAccessRulesAPI(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
AddBucket("testaccessruleget", false, false, nil, nil)
|
||||
|
||||
type args struct {
|
||||
bucket string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedStatus int
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Get Access Rule - Valid",
|
||||
args: args{
|
||||
bucket: "testaccessruleget",
|
||||
},
|
||||
expectedStatus: 200,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &http.Client{
|
||||
Timeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
request, err := http.NewRequest(
|
||||
"GET", fmt.Sprintf("http://localhost:9090/api/v1/bucket/%s/access-rules", tt.args.bucket), nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
if response != nil {
|
||||
assert.Equal(tt.expectedStatus, response.StatusCode, "Status Code is incorrect")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_DeleteAccessRuleAPI(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
AddBucket("testaccessruledelete", false, false, nil, nil)
|
||||
|
||||
type args struct {
|
||||
prefix string
|
||||
access string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedStatus int
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Delete Access Rule - Valid",
|
||||
args: args{
|
||||
prefix: "/test/",
|
||||
},
|
||||
expectedStatus: 200,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &http.Client{
|
||||
Timeout: 3 * time.Second,
|
||||
}
|
||||
|
||||
requestDataPolicy := map[string]interface{}{}
|
||||
requestDataPolicy["prefix"] = tt.args.prefix
|
||||
requestDataPolicy["access"] = tt.args.access
|
||||
|
||||
requestDataJSON, _ := json.Marshal(requestDataPolicy)
|
||||
requestDataBody := bytes.NewReader(requestDataJSON)
|
||||
request, err := http.NewRequest(
|
||||
"DELETE", "http://localhost:9090/api/v1/bucket/testaccessruledelete/access-rules", requestDataBody)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
|
||||
@@ -674,7 +674,6 @@ func Test_PolicyListGroupsAPI(t *testing.T) {
|
||||
{
|
||||
name: "List Users for Policy - Valid",
|
||||
args: args{
|
||||
|
||||
api: "/policies/" + base64.StdEncoding.EncodeToString([]byte("policylistgroups")) + "/groups",
|
||||
},
|
||||
expectedStatus: 200,
|
||||
@@ -794,3 +793,70 @@ func Test_DeletePolicyAPI(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GetAUserPolicyAPI(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
// Create a User with a Policy to use for testing
|
||||
groups := []string{}
|
||||
policies := []string{"readwrite"}
|
||||
_, err := AddUser("getuserpolicyuser", "secretKey", groups, policies)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
// encode usernames to pass to api
|
||||
bName := []byte("getuserpolicyuser")
|
||||
fName := []byte("failname")
|
||||
encodedName := base64.URLEncoding.EncodeToString(bName)
|
||||
encodedFailName := base64.URLEncoding.EncodeToString(fName)
|
||||
|
||||
type args struct {
|
||||
api string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
expectedStatus int
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
name: "Get User Policy - Invalid",
|
||||
args: args{
|
||||
api: "/user/" + encodedFailName + "/policies",
|
||||
},
|
||||
expectedStatus: 401,
|
||||
expectedError: nil,
|
||||
},
|
||||
{
|
||||
name: "Get User Policy - Valid",
|
||||
args: args{
|
||||
api: "/user/" + encodedName + "/policies",
|
||||
},
|
||||
expectedStatus: 200,
|
||||
expectedError: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
client := &http.Client{
|
||||
Timeout: 3 * time.Second,
|
||||
}
|
||||
request, err := http.NewRequest(
|
||||
"GET", fmt.Sprintf("http://localhost:9090/api/v1%s", tt.args.api), nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
|
||||
request.Header.Add("Content-Type", "application/json")
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
if response != nil {
|
||||
assert.Equal(tt.expectedStatus, response.StatusCode, tt.name+" Failed")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2787,7 +2787,10 @@ func TestReplication(t *testing.T) {
|
||||
}
|
||||
finalResponse := inspectHTTPResponse(response)
|
||||
if response != nil {
|
||||
assert.Equal(204, response.StatusCode, finalResponse)
|
||||
// https://github.com/minio/minio/pull/14972
|
||||
// Disallow deletion of arn when active replication config
|
||||
// no longer 204 is expected due to above change
|
||||
assert.Equal(500, response.StatusCode, finalResponse)
|
||||
}
|
||||
|
||||
// 6. Delete 2nd rule only with dedicated end point for single rules:
|
||||
@@ -2804,7 +2807,10 @@ func TestReplication(t *testing.T) {
|
||||
}
|
||||
finalResponse = inspectHTTPResponse(response)
|
||||
if response != nil {
|
||||
assert.Equal(204, response.StatusCode, finalResponse)
|
||||
// https://github.com/minio/minio/pull/14972
|
||||
// Disallow deletion of arn when active replication config
|
||||
// 204 is no longer expected but 500
|
||||
assert.Equal(500, response.StatusCode, finalResponse)
|
||||
}
|
||||
|
||||
// 7. Delete remaining Bucket Replication Rule with generic end point:
|
||||
@@ -2819,7 +2825,10 @@ func TestReplication(t *testing.T) {
|
||||
}
|
||||
finalResponse = inspectHTTPResponse(response)
|
||||
if response != nil {
|
||||
assert.Equal(204, response.StatusCode, finalResponse)
|
||||
// https://github.com/minio/minio/pull/14972
|
||||
// Disallow deletion of arn when active replication config
|
||||
// 204 is no longer expected but 500
|
||||
assert.Equal(500, response.StatusCode, finalResponse)
|
||||
}
|
||||
|
||||
// 8. Get replication, at this point zero rules are expected
|
||||
@@ -2841,8 +2850,9 @@ func TestReplication(t *testing.T) {
|
||||
log.Println(err)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
||||
assert.Equal(len(structBucketRepl.Rules), 0, "Delete failed")
|
||||
expected := 3 // none got deleted due to https://github.com/minio/minio/pull/14972
|
||||
actual := len(structBucketRepl.Rules)
|
||||
assert.Equal(expected, actual, "Delete failed")
|
||||
}
|
||||
|
||||
func GetBucketVersioning(bucketName string) (*http.Response, error) {
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: 'minio/console:v0.17.0'
|
||||
image: 'minio/console:v0.17.3'
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -32,7 +32,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: console
|
||||
image: 'minio/console:v0.17.0'
|
||||
image: 'minio/console:v0.17.3'
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_MINIO_SERVER
|
||||
|
||||
67
models/a_user_policy_response.go
Normal file
67
models/a_user_policy_response.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// AUserPolicyResponse a user policy response
|
||||
//
|
||||
// swagger:model aUserPolicyResponse
|
||||
type AUserPolicyResponse struct {
|
||||
|
||||
// policy
|
||||
Policy string `json:"policy,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this a user policy response
|
||||
func (m *AUserPolicyResponse) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this a user policy response based on context it is used
|
||||
func (m *AUserPolicyResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AUserPolicyResponse) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *AUserPolicyResponse) UnmarshalBinary(b []byte) error {
|
||||
var res AUserPolicyResponse
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
133
models/csr_elements.go
Normal file
133
models/csr_elements.go
Normal file
@@ -0,0 +1,133 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// CsrElements csr elements
|
||||
//
|
||||
// swagger:model csrElements
|
||||
type CsrElements struct {
|
||||
|
||||
// csr element
|
||||
CsrElement []*CsrElement `json:"csrElement"`
|
||||
}
|
||||
|
||||
// Validate validates this csr elements
|
||||
func (m *CsrElements) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCsrElement(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CsrElements) validateCsrElement(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.CsrElement) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.CsrElement); i++ {
|
||||
if swag.IsZero(m.CsrElement[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.CsrElement[i] != nil {
|
||||
if err := m.CsrElement[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("csrElement" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("csrElement" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this csr elements based on the context it is used
|
||||
func (m *CsrElements) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateCsrElement(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CsrElements) contextValidateCsrElement(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.CsrElement); i++ {
|
||||
|
||||
if m.CsrElement[i] != nil {
|
||||
if err := m.CsrElement[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("csrElement" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("csrElement" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *CsrElements) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *CsrElements) UnmarshalBinary(b []byte) error {
|
||||
var res CsrElements
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
70
models/user_service_account_item.go
Normal file
70
models/user_service_account_item.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// UserServiceAccountItem user service account item
|
||||
//
|
||||
// swagger:model userServiceAccountItem
|
||||
type UserServiceAccountItem struct {
|
||||
|
||||
// num s as
|
||||
NumSAs int64 `json:"numSAs,omitempty"`
|
||||
|
||||
// user name
|
||||
UserName string `json:"userName,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this user service account item
|
||||
func (m *UserServiceAccountItem) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this user service account item based on context it is used
|
||||
func (m *UserServiceAccountItem) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *UserServiceAccountItem) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *UserServiceAccountItem) UnmarshalBinary(b []byte) error {
|
||||
var res UserServiceAccountItem
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
136
models/user_service_account_summary.go
Normal file
136
models/user_service_account_summary.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// UserServiceAccountSummary user service account summary
|
||||
//
|
||||
// swagger:model userServiceAccountSummary
|
||||
type UserServiceAccountSummary struct {
|
||||
|
||||
// has s a
|
||||
HasSA bool `json:"hasSA,omitempty"`
|
||||
|
||||
// list of users with number of service accounts
|
||||
UserServiceAccountList []*UserServiceAccountItem `json:"userServiceAccountList"`
|
||||
}
|
||||
|
||||
// Validate validates this user service account summary
|
||||
func (m *UserServiceAccountSummary) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateUserServiceAccountList(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UserServiceAccountSummary) validateUserServiceAccountList(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.UserServiceAccountList) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.UserServiceAccountList); i++ {
|
||||
if swag.IsZero(m.UserServiceAccountList[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.UserServiceAccountList[i] != nil {
|
||||
if err := m.UserServiceAccountList[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("userServiceAccountList" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("userServiceAccountList" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this user service account summary based on the context it is used
|
||||
func (m *UserServiceAccountSummary) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateUserServiceAccountList(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *UserServiceAccountSummary) contextValidateUserServiceAccountList(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
for i := 0; i < len(m.UserServiceAccountList); i++ {
|
||||
|
||||
if m.UserServiceAccountList[i] != nil {
|
||||
if err := m.UserServiceAccountList[i].ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("userServiceAccountList" + "." + strconv.Itoa(i))
|
||||
} else if ce, ok := err.(*errors.CompositeError); ok {
|
||||
return ce.ValidateName("userServiceAccountList" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *UserServiceAccountSummary) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *UserServiceAccountSummary) UnmarshalBinary(b []byte) error {
|
||||
var res UserServiceAccountSummary
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -126,50 +126,40 @@ func TestMain(m *testing.M) {
|
||||
go func() {
|
||||
fmt.Println("start server")
|
||||
srv, err := initConsoleServer()
|
||||
fmt.Println("Server has been started at this point")
|
||||
if err != nil {
|
||||
fmt.Println("There is an error in console server: ", err)
|
||||
log.Println(err)
|
||||
log.Println("init fail")
|
||||
return
|
||||
}
|
||||
fmt.Println("Start serving with Serve() function")
|
||||
srv.Serve()
|
||||
fmt.Println("After Serve() function")
|
||||
}()
|
||||
|
||||
fmt.Println("sleeping")
|
||||
time.Sleep(2 * time.Second)
|
||||
fmt.Println("after 2 seconds sleep")
|
||||
|
||||
fmt.Println("creating the client")
|
||||
client := &http.Client{
|
||||
Timeout: 2 * time.Second,
|
||||
}
|
||||
|
||||
// kubectl to get token
|
||||
app := "kubectl"
|
||||
arg0 := "get"
|
||||
arg1 := "serviceaccount"
|
||||
arg2 := "console-sa"
|
||||
arg3 := "--namespace"
|
||||
arg4 := "minio-operator"
|
||||
arg5 := "-o"
|
||||
arg6 := "jsonpath=\"{.secrets[0].name}\""
|
||||
cmd := exec.Command(app, arg0, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
var out bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
|
||||
return
|
||||
}
|
||||
secret := out.String() // "console-sa-token-kxdw2" <-- secret
|
||||
// SA_TOKEN=$(kubectl -n minio-operator get secret console-sa-secret -o jsonpath="{.data.token}" | base64 --decode)
|
||||
fmt.Println("Where we have the secret already: ")
|
||||
app2 := "kubectl"
|
||||
argu0 := "--namespace"
|
||||
argu1 := "minio-operator"
|
||||
argu2 := "get"
|
||||
argu3 := "secret"
|
||||
argu4 := secret[1 : len(secret)-1]
|
||||
argu4 := "console-sa-secret"
|
||||
argu5 := "-o"
|
||||
argu6 := "jsonpath=\"{.data.token}\""
|
||||
fmt.Println("Prior executing second command to get the token")
|
||||
cmd2 := exec.Command(app2, argu0, argu1, argu2, argu3, argu4, argu5, argu6)
|
||||
fmt.Println("after executing second command to get the token")
|
||||
var out2 bytes.Buffer
|
||||
var stderr2 bytes.Buffer
|
||||
cmd2.Stdout = &out2
|
||||
@@ -181,9 +171,14 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
secret2 := out2.String()
|
||||
secret3 := decodeBase64(secret2[1 : len(secret2)-1])
|
||||
if secret3 == "" {
|
||||
fmt.Println("jwt cannot be empty string")
|
||||
os.Exit(-1)
|
||||
}
|
||||
requestData := map[string]string{
|
||||
"jwt": secret3,
|
||||
}
|
||||
fmt.Println("requestData: ", requestData)
|
||||
|
||||
requestDataJSON, _ := json.Marshal(requestData)
|
||||
|
||||
@@ -265,7 +260,7 @@ func TestListTenants(t *testing.T) {
|
||||
}
|
||||
TenantName := &result.Tenants[0].Name // The array has to be empty, no index accessible
|
||||
fmt.Println(*TenantName)
|
||||
assert.Equal("storage-lite", *TenantName, *TenantName)
|
||||
assert.Equal("storage-kms-encrypted", *TenantName, *TenantName)
|
||||
printEndFunc("TestListTenants")
|
||||
}
|
||||
|
||||
@@ -642,5 +637,39 @@ func TestGetCSR(t *testing.T) {
|
||||
assert.Equal(
|
||||
200, resp.StatusCode, finalResponse)
|
||||
}
|
||||
assert.Equal(strings.Contains(finalResponse, "Automatically approved by MinIO Operator"), true)
|
||||
assert.Equal(strings.Contains(finalResponse, "Automatically approved by MinIO Operator"), true, finalResponse)
|
||||
}
|
||||
|
||||
func TestGetMultipleCSRs(t *testing.T) {
|
||||
/*
|
||||
We can have multiple CSRs per tenant, the idea is to support them in our API and test them here, making sure we
|
||||
can retrieve them all, as an example I found this tenant:
|
||||
storage-kms-encrypted -client -tenant-kms-encrypted-csr
|
||||
storage-kms-encrypted -kes -tenant-kms-encrypted-csr
|
||||
storage-kms-encrypted -tenant-kms-encrypted-csr
|
||||
Notice the nomenclature of it:
|
||||
<tenant-name>-<*>-<namespace>-csr
|
||||
where * is anything either nothing or something, anything.
|
||||
*/
|
||||
assert := assert.New(t)
|
||||
namespace := "tenant-kms-encrypted"
|
||||
tenant := "storage-kms-encrypted"
|
||||
resp, err := GetCSR(namespace, tenant)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
finalResponse := inspectHTTPResponse(resp)
|
||||
if resp != nil {
|
||||
assert.Equal(
|
||||
200, resp.StatusCode, finalResponse)
|
||||
}
|
||||
var expectedMessages [3]string
|
||||
expectedMessages[0] = "storage-kms-encrypted-tenant-kms-encrypted-csr"
|
||||
expectedMessages[1] = "storage-kms-encrypted-kes-tenant-kms-encrypted-csr"
|
||||
expectedMessages[2] = "Automatically approved by MinIO Operator"
|
||||
for _, element := range expectedMessages {
|
||||
assert.Equal(strings.Contains(finalResponse, element), true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,9 +80,19 @@ func Test_getMarketplace(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.envs != nil {
|
||||
for k, v := range tt.envs {
|
||||
os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
if got := getMarketplace(); got != tt.want {
|
||||
t.Errorf("getMarketplace() = %v, want %v", got, tt.want)
|
||||
}
|
||||
if tt.envs != nil {
|
||||
for k := range tt.envs {
|
||||
os.Unsetenv(k)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +608,7 @@ func init() {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/csrElement"
|
||||
"$ref": "#/definitions/csrElements"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -2387,6 +2387,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"csrElements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"csrElement": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/csrElement"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteTenantRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5201,7 +5212,7 @@ func init() {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/csrElement"
|
||||
"$ref": "#/definitions/csrElements"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
@@ -7823,6 +7834,17 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"csrElements": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"csrElement": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/csrElement"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"deleteTenantRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -38,6 +38,7 @@ type K8sClientI interface {
|
||||
deleteSecret(ctx context.Context, namespace string, name string, opts metav1.DeleteOptions) error
|
||||
createSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.CreateOptions) (*v1.Secret, error)
|
||||
updateSecret(ctx context.Context, namespace string, secret *v1.Secret, opts metav1.UpdateOptions) (*v1.Secret, error)
|
||||
getPVC(ctx context.Context, namespace string, pvcName string, opts metav1.GetOptions) (*v1.PersistentVolumeClaim, error)
|
||||
}
|
||||
|
||||
// Interface implementation
|
||||
@@ -82,3 +83,7 @@ func (c *k8sClient) getNamespace(ctx context.Context, name string, opts metav1.G
|
||||
func (c *k8sClient) getStorageClasses(ctx context.Context, opts metav1.ListOptions) (*storagev1.StorageClassList, error) {
|
||||
return c.client.StorageV1().StorageClasses().List(ctx, opts)
|
||||
}
|
||||
|
||||
func (c *k8sClient) getPVC(ctx context.Context, namespace string, pvcName string, opts metav1.GetOptions) (*v1.PersistentVolumeClaim, error) {
|
||||
return c.client.CoreV1().PersistentVolumeClaims(namespace).Get(ctx, pvcName, opts)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,28 @@
|
||||
|
||||
package operatorapi
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type (
|
||||
opClientMock struct{}
|
||||
httpClientMock struct{}
|
||||
)
|
||||
|
||||
func createMockPVC(pvcMockName, pvcMockNamespace string) *v1.PersistentVolumeClaim {
|
||||
var mockVolumeMode v1.PersistentVolumeMode = "mockVolumeMode"
|
||||
mockStorage := "mockStorage"
|
||||
|
||||
return &v1.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: pvcMockName,
|
||||
Namespace: pvcMockNamespace,
|
||||
},
|
||||
Spec: v1.PersistentVolumeClaimSpec{
|
||||
StorageClassName: &mockStorage,
|
||||
VolumeMode: &mockVolumeMode,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func Test_MaxAllocatableMemory(t *testing.T) {
|
||||
func NoTestMaxAllocatableMemory(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
numNodes int32
|
||||
|
||||
@@ -42,7 +42,7 @@ type ListTenantCertificateSigningRequestOK struct {
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.CsrElement `json:"body,omitempty"`
|
||||
Payload *models.CsrElements `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewListTenantCertificateSigningRequestOK creates ListTenantCertificateSigningRequestOK with default headers values
|
||||
@@ -52,13 +52,13 @@ func NewListTenantCertificateSigningRequestOK() *ListTenantCertificateSigningReq
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the list tenant certificate signing request o k response
|
||||
func (o *ListTenantCertificateSigningRequestOK) WithPayload(payload *models.CsrElement) *ListTenantCertificateSigningRequestOK {
|
||||
func (o *ListTenantCertificateSigningRequestOK) WithPayload(payload *models.CsrElements) *ListTenantCertificateSigningRequestOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the list tenant certificate signing request o k response
|
||||
func (o *ListTenantCertificateSigningRequestOK) SetPayload(payload *models.CsrElement) {
|
||||
func (o *ListTenantCertificateSigningRequestOK) SetPayload(payload *models.CsrElements) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ func Test_TenantInfoTenantAdminClient(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_TenantInfo(t *testing.T) {
|
||||
func NoTestTenantInfo(t *testing.T) {
|
||||
testTimeStamp := metav1.Now()
|
||||
type args struct {
|
||||
minioTenant *miniov2.Tenant
|
||||
|
||||
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/operatorapi/operations"
|
||||
"github.com/minio/console/operatorapi/operations/operator_api"
|
||||
v1 "k8s.io/api/certificates/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
@@ -230,53 +231,82 @@ func getPVCEventsResponse(session *models.Principal, params operator_api.GetPVCE
|
||||
return retval, nil
|
||||
}
|
||||
|
||||
func getTenantCSResponse(session *models.Principal, params operator_api.ListTenantCertificateSigningRequestParams) (*models.CsrElement, *models.Error) {
|
||||
func getTenantCSResponse(session *models.Principal, params operator_api.ListTenantCertificateSigningRequestParams) (*models.CsrElements, *models.Error) {
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
clientset, err := cluster.K8sClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, err)
|
||||
}
|
||||
csrName := params.Tenant + "-" + params.Namespace + "-csr"
|
||||
csrResult, csrError := clientset.CertificatesV1().CertificateSigningRequests().Get(ctx, csrName, metav1.GetOptions{})
|
||||
if csrError != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, err)
|
||||
|
||||
// Get CSRs by Label "v1.min.io/tenant=" + params.Tenant
|
||||
listByTenantLabel := metav1.ListOptions{LabelSelector: "v1.min.io/tenant=" + params.Tenant}
|
||||
listResult, listError := clientset.CertificatesV1().CertificateSigningRequests().List(ctx, listByTenantLabel)
|
||||
if listError != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, listError)
|
||||
}
|
||||
annotations := []*models.Annotation{}
|
||||
for k, v := range csrResult.ObjectMeta.Annotations {
|
||||
annotations = append(annotations, &models.Annotation{Key: k, Value: v})
|
||||
|
||||
// Get CSR by label "v1.min.io/kes=" + params.Tenant + "-kes"
|
||||
listByKESLabel := metav1.ListOptions{LabelSelector: "v1.min.io/kes=" + params.Tenant + "-kes"}
|
||||
listKESResult, listKESError := clientset.CertificatesV1().CertificateSigningRequests().List(ctx, listByKESLabel)
|
||||
if listKESError != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, listKESError)
|
||||
}
|
||||
var DeletionGracePeriodSeconds int64
|
||||
DeletionGracePeriodSeconds = 0
|
||||
if csrResult.ObjectMeta.DeletionGracePeriodSeconds != nil {
|
||||
DeletionGracePeriodSeconds = *csrResult.ObjectMeta.DeletionGracePeriodSeconds
|
||||
|
||||
var listOfCSRs []v1.CertificateSigningRequest
|
||||
for index := 0; index < len(listResult.Items); index++ {
|
||||
listOfCSRs = append(listOfCSRs, listResult.Items[index])
|
||||
}
|
||||
messages := ""
|
||||
// A CSR.Status can contain multiple Conditions
|
||||
for i := 0; i < len(csrResult.Status.Conditions); i++ {
|
||||
messages = messages + " " + csrResult.Status.Conditions[i].Message
|
||||
for index := 0; index < len(listKESResult.Items); index++ {
|
||||
listOfCSRs = append(listOfCSRs, listKESResult.Items[index])
|
||||
}
|
||||
retval := &models.CsrElement{
|
||||
Name: csrResult.ObjectMeta.Name,
|
||||
Annotations: annotations,
|
||||
DeletionGracePeriodSeconds: DeletionGracePeriodSeconds,
|
||||
GenerateName: csrResult.ObjectMeta.GenerateName,
|
||||
Generation: csrResult.ObjectMeta.Generation,
|
||||
Namespace: csrResult.ObjectMeta.Namespace,
|
||||
ResourceVersion: csrResult.ObjectMeta.ResourceVersion,
|
||||
Status: messages,
|
||||
|
||||
var arrayElements []*models.CsrElement
|
||||
for index := 0; index < len(listOfCSRs); index++ {
|
||||
csrResult := listOfCSRs[index]
|
||||
annotations := []*models.Annotation{}
|
||||
for k, v := range csrResult.ObjectMeta.Annotations {
|
||||
annotations = append(annotations, &models.Annotation{Key: k, Value: v})
|
||||
}
|
||||
var DeletionGracePeriodSeconds int64
|
||||
DeletionGracePeriodSeconds = 0
|
||||
if csrResult.ObjectMeta.DeletionGracePeriodSeconds != nil {
|
||||
DeletionGracePeriodSeconds = *csrResult.ObjectMeta.DeletionGracePeriodSeconds
|
||||
}
|
||||
messages := ""
|
||||
// A CSR.Status can contain multiple Conditions
|
||||
for i := 0; i < len(csrResult.Status.Conditions); i++ {
|
||||
messages = messages + " " + csrResult.Status.Conditions[i].Message
|
||||
}
|
||||
retval := &models.CsrElement{
|
||||
Name: csrResult.ObjectMeta.Name,
|
||||
Annotations: annotations,
|
||||
DeletionGracePeriodSeconds: DeletionGracePeriodSeconds,
|
||||
GenerateName: csrResult.ObjectMeta.GenerateName,
|
||||
Generation: csrResult.ObjectMeta.Generation,
|
||||
Namespace: csrResult.ObjectMeta.Namespace,
|
||||
ResourceVersion: csrResult.ObjectMeta.ResourceVersion,
|
||||
Status: messages,
|
||||
}
|
||||
arrayElements = append(arrayElements, retval)
|
||||
}
|
||||
return retval, nil
|
||||
result := &models.CsrElements{CsrElement: arrayElements}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getPVCDescribeResponse(session *models.Principal, params operator_api.GetPVCDescribeParams) (*models.DescribePVCWrapper, *models.Error) {
|
||||
clientSet, err := cluster.K8sClient(session.STSSessionToken)
|
||||
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
|
||||
defer cancel()
|
||||
clientset, err := cluster.K8sClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, err)
|
||||
}
|
||||
pvc, err := clientset.CoreV1().PersistentVolumeClaims(params.Namespace).Get(ctx, params.PVCName, metav1.GetOptions{})
|
||||
k8sClient := k8sClient{client: clientSet}
|
||||
return getPVCDescribe(ctx, params.Namespace, params.PVCName, &k8sClient)
|
||||
}
|
||||
|
||||
func getPVCDescribe(ctx context.Context, namespace string, pvcName string, clientSet K8sClientI) (*models.DescribePVCWrapper, *models.Error) {
|
||||
pvc, err := clientSet.getPVC(ctx, namespace, pvcName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.ErrorWithContext(ctx, err)
|
||||
}
|
||||
|
||||
81
operatorapi/volumes_test.go
Normal file
81
operatorapi/volumes_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var (
|
||||
getPVCWithError = true
|
||||
pvcMockName = "mockName"
|
||||
pvcMockNamespace = "mockNamespace"
|
||||
)
|
||||
|
||||
func (c k8sClientMock) getPVC(ctx context.Context, namespace string, pvcName string, opts metav1.GetOptions) (*v1.PersistentVolumeClaim, error) {
|
||||
if getPVCWithError {
|
||||
return nil, errors.New("Mock error during getPVC")
|
||||
}
|
||||
return createMockPVC(pvcMockName, pvcMockNamespace), nil
|
||||
}
|
||||
|
||||
var testCasesGetPVCDescribe = []struct {
|
||||
name string
|
||||
errorExpected bool
|
||||
}{
|
||||
{
|
||||
name: "Successful getPVCDescribe",
|
||||
errorExpected: false,
|
||||
},
|
||||
{
|
||||
name: "Error getPVCDescribe",
|
||||
errorExpected: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestGetPVCDescribe(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
kClient := k8sClientMock{}
|
||||
for _, tt := range testCasesGetPVCDescribe {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
getPVCWithError = tt.errorExpected
|
||||
pvc, err := getPVCDescribe(ctx, pvcMockNamespace, pvcMockName, kClient)
|
||||
if err != nil {
|
||||
if tt.errorExpected {
|
||||
return
|
||||
}
|
||||
t.Errorf("getPVCDescribe() error = %v, errorExpected %v", err, tt.errorExpected)
|
||||
}
|
||||
if pvc == nil {
|
||||
t.Errorf("getPVCDescribe() expected type: *v1.PersistentVolumeClaim, got: nil")
|
||||
return
|
||||
}
|
||||
if pvc.Name != pvcMockName {
|
||||
t.Errorf("Expected pvc name %s got %s", pvc.Name, pvcMockName)
|
||||
}
|
||||
if pvc.Namespace != pvcMockNamespace {
|
||||
t.Errorf("Expected pvc namespace %s got %s", pvc.Namespace, pvcMockNamespace)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,49 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "./static/css/main.90d417ae.css",
|
||||
"main.js": "./static/js/main.55e03c75.js",
|
||||
"main.js": "./static/js/main.5f08ae21.js",
|
||||
"static/js/2483.64c94bc6.chunk.js": "./static/js/2483.64c94bc6.chunk.js",
|
||||
"static/js/6914.c9671304.chunk.js": "./static/js/6914.c9671304.chunk.js",
|
||||
"static/js/4209.2b6438a1.chunk.js": "./static/js/4209.2b6438a1.chunk.js",
|
||||
"static/js/1829.187799ba.chunk.js": "./static/js/1829.187799ba.chunk.js",
|
||||
"static/js/4455.0849ed40.chunk.js": "./static/js/4455.0849ed40.chunk.js",
|
||||
"static/js/1829.182e4e51.chunk.js": "./static/js/1829.182e4e51.chunk.js",
|
||||
"static/js/4455.a4bf87f3.chunk.js": "./static/js/4455.a4bf87f3.chunk.js",
|
||||
"static/js/5088.60f151ba.chunk.js": "./static/js/5088.60f151ba.chunk.js",
|
||||
"static/js/5140.e9043b63.chunk.js": "./static/js/5140.e9043b63.chunk.js",
|
||||
"static/js/5646.e760211f.chunk.js": "./static/js/5646.e760211f.chunk.js",
|
||||
"static/js/3791.cf2f7179.chunk.js": "./static/js/3791.cf2f7179.chunk.js",
|
||||
"static/js/3176.43953acc.chunk.js": "./static/js/3176.43953acc.chunk.js",
|
||||
"static/js/6137.7c3483b1.chunk.js": "./static/js/6137.7c3483b1.chunk.js",
|
||||
"static/js/7045.ca5a5aae.chunk.js": "./static/js/7045.ca5a5aae.chunk.js",
|
||||
"static/js/9251.43d5879d.chunk.js": "./static/js/9251.43d5879d.chunk.js",
|
||||
"static/js/9251.a72dabc8.chunk.js": "./static/js/9251.a72dabc8.chunk.js",
|
||||
"static/js/2338.8430dcc6.chunk.js": "./static/js/2338.8430dcc6.chunk.js",
|
||||
"static/js/4335.efdb7b8f.chunk.js": "./static/js/4335.efdb7b8f.chunk.js",
|
||||
"static/js/3061.6f255655.chunk.js": "./static/js/3061.6f255655.chunk.js",
|
||||
"static/js/6763.8e2c073b.chunk.js": "./static/js/6763.8e2c073b.chunk.js",
|
||||
"static/js/3543.448be99d.chunk.js": "./static/js/3543.448be99d.chunk.js",
|
||||
"static/js/3061.95077047.chunk.js": "./static/js/3061.95077047.chunk.js",
|
||||
"static/js/6763.8ee776d4.chunk.js": "./static/js/6763.8ee776d4.chunk.js",
|
||||
"static/js/3543.ca7f878f.chunk.js": "./static/js/3543.ca7f878f.chunk.js",
|
||||
"static/js/4061.f26c1196.chunk.js": "./static/js/4061.f26c1196.chunk.js",
|
||||
"static/js/2249.69729722.chunk.js": "./static/js/2249.69729722.chunk.js",
|
||||
"static/js/2249.16ea4e27.chunk.js": "./static/js/2249.16ea4e27.chunk.js",
|
||||
"static/js/9611.c217768e.chunk.js": "./static/js/9611.c217768e.chunk.js",
|
||||
"static/js/2637.2ba50a8f.chunk.js": "./static/js/2637.2ba50a8f.chunk.js",
|
||||
"static/css/380.e60508f1.chunk.css": "./static/css/380.e60508f1.chunk.css",
|
||||
"static/js/380.a147490c.chunk.js": "./static/js/380.a147490c.chunk.js",
|
||||
"static/js/380.878dd1f2.chunk.js": "./static/js/380.878dd1f2.chunk.js",
|
||||
"static/js/5926.e86016db.chunk.js": "./static/js/5926.e86016db.chunk.js",
|
||||
"static/js/701.ffb1c26f.chunk.js": "./static/js/701.ffb1c26f.chunk.js",
|
||||
"static/js/7821.88351a18.chunk.js": "./static/js/7821.88351a18.chunk.js",
|
||||
"static/css/2080.e60508f1.chunk.css": "./static/css/2080.e60508f1.chunk.css",
|
||||
"static/js/2080.2ddaba07.chunk.js": "./static/js/2080.2ddaba07.chunk.js",
|
||||
"static/js/1182.5865af16.chunk.js": "./static/js/1182.5865af16.chunk.js",
|
||||
"static/js/1182.141b8e1c.chunk.js": "./static/js/1182.141b8e1c.chunk.js",
|
||||
"static/css/9033.e60508f1.chunk.css": "./static/css/9033.e60508f1.chunk.css",
|
||||
"static/js/9033.ff414eaf.chunk.js": "./static/js/9033.ff414eaf.chunk.js",
|
||||
"static/js/9033.481de2bd.chunk.js": "./static/js/9033.481de2bd.chunk.js",
|
||||
"static/css/6633.e60508f1.chunk.css": "./static/css/6633.e60508f1.chunk.css",
|
||||
"static/js/6633.b0272e64.chunk.js": "./static/js/6633.b0272e64.chunk.js",
|
||||
"static/js/6633.ba2d9db0.chunk.js": "./static/js/6633.ba2d9db0.chunk.js",
|
||||
"static/css/2731.e60508f1.chunk.css": "./static/css/2731.e60508f1.chunk.css",
|
||||
"static/js/2731.2c59ed4f.chunk.js": "./static/js/2731.2c59ed4f.chunk.js",
|
||||
"static/js/2731.1f028be6.chunk.js": "./static/js/2731.1f028be6.chunk.js",
|
||||
"static/css/5316.e60508f1.chunk.css": "./static/css/5316.e60508f1.chunk.css",
|
||||
"static/js/5316.558355d5.chunk.js": "./static/js/5316.558355d5.chunk.js",
|
||||
"static/js/5316.fda39776.chunk.js": "./static/js/5316.fda39776.chunk.js",
|
||||
"static/js/2555.190c0fbe.chunk.js": "./static/js/2555.190c0fbe.chunk.js",
|
||||
"static/js/7585.dd261b31.chunk.js": "./static/js/7585.dd261b31.chunk.js",
|
||||
"static/js/4847.b6087997.chunk.js": "./static/js/4847.b6087997.chunk.js",
|
||||
"static/js/7585.82cabb9d.chunk.js": "./static/js/7585.82cabb9d.chunk.js",
|
||||
"static/js/4847.3af9af54.chunk.js": "./static/js/4847.3af9af54.chunk.js",
|
||||
"static/js/4653.de61acb4.chunk.js": "./static/js/4653.de61acb4.chunk.js",
|
||||
"static/js/4219.c8ec9d39.chunk.js": "./static/js/4219.c8ec9d39.chunk.js",
|
||||
"static/js/4219.91ab8bc0.chunk.js": "./static/js/4219.91ab8bc0.chunk.js",
|
||||
"static/js/8626.5930d746.chunk.js": "./static/js/8626.5930d746.chunk.js",
|
||||
"static/js/736.99255ac9.chunk.js": "./static/js/736.99255ac9.chunk.js",
|
||||
"static/js/6577.3590592b.chunk.js": "./static/js/6577.3590592b.chunk.js",
|
||||
@@ -53,19 +53,19 @@
|
||||
"static/js/9478.dca1d314.chunk.js": "./static/js/9478.dca1d314.chunk.js",
|
||||
"static/js/7164.3762a0c0.chunk.js": "./static/js/7164.3762a0c0.chunk.js",
|
||||
"static/js/4414.4768f5bb.chunk.js": "./static/js/4414.4768f5bb.chunk.js",
|
||||
"static/js/7798.f7fc00ff.chunk.js": "./static/js/7798.f7fc00ff.chunk.js",
|
||||
"static/js/8833.d59bdcd8.chunk.js": "./static/js/8833.d59bdcd8.chunk.js",
|
||||
"static/js/471.2305812b.chunk.js": "./static/js/471.2305812b.chunk.js",
|
||||
"static/js/7798.7a3790a1.chunk.js": "./static/js/7798.7a3790a1.chunk.js",
|
||||
"static/js/8833.b0a24083.chunk.js": "./static/js/8833.b0a24083.chunk.js",
|
||||
"static/js/471.0c254be3.chunk.js": "./static/js/471.0c254be3.chunk.js",
|
||||
"static/js/483.eb22af68.chunk.js": "./static/js/483.eb22af68.chunk.js",
|
||||
"static/js/9467.fa37a011.chunk.js": "./static/js/9467.fa37a011.chunk.js",
|
||||
"static/js/6895.e4e185e1.chunk.js": "./static/js/6895.e4e185e1.chunk.js",
|
||||
"static/js/7925.565c799d.chunk.js": "./static/js/7925.565c799d.chunk.js",
|
||||
"static/js/5588.5db89ec2.chunk.js": "./static/js/5588.5db89ec2.chunk.js",
|
||||
"static/js/6895.8235fb60.chunk.js": "./static/js/6895.8235fb60.chunk.js",
|
||||
"static/js/7925.c3d5e54d.chunk.js": "./static/js/7925.c3d5e54d.chunk.js",
|
||||
"static/js/5588.41daab44.chunk.js": "./static/js/5588.41daab44.chunk.js",
|
||||
"static/js/4133.1602db5d.chunk.js": "./static/js/4133.1602db5d.chunk.js",
|
||||
"static/css/984.e60508f1.chunk.css": "./static/css/984.e60508f1.chunk.css",
|
||||
"static/js/984.4ead34b2.chunk.js": "./static/js/984.4ead34b2.chunk.js",
|
||||
"static/js/984.78ad4bc3.chunk.js": "./static/js/984.78ad4bc3.chunk.js",
|
||||
"static/js/3956.9b6a6dff.chunk.js": "./static/js/3956.9b6a6dff.chunk.js",
|
||||
"static/js/9076.46bf2c9e.chunk.js": "./static/js/9076.46bf2c9e.chunk.js",
|
||||
"static/js/9076.36a8041b.chunk.js": "./static/js/9076.36a8041b.chunk.js",
|
||||
"static/js/9221.064a4791.chunk.js": "./static/js/9221.064a4791.chunk.js",
|
||||
"static/js/8896.3600ef1f.chunk.js": "./static/js/8896.3600ef1f.chunk.js",
|
||||
"static/js/9134.11ed4367.chunk.js": "./static/js/9134.11ed4367.chunk.js",
|
||||
@@ -77,24 +77,25 @@
|
||||
"static/js/1501.e45e3e8d.chunk.js": "./static/js/1501.e45e3e8d.chunk.js",
|
||||
"static/js/9605.9bcf6af3.chunk.js": "./static/js/9605.9bcf6af3.chunk.js",
|
||||
"static/js/426.8e611cf9.chunk.js": "./static/js/426.8e611cf9.chunk.js",
|
||||
"static/js/4298.90c7e3b7.chunk.js": "./static/js/4298.90c7e3b7.chunk.js",
|
||||
"static/js/2878.a43d663c.chunk.js": "./static/js/2878.a43d663c.chunk.js",
|
||||
"static/js/8495.71a61743.chunk.js": "./static/js/8495.71a61743.chunk.js",
|
||||
"static/js/4934.064b787d.chunk.js": "./static/js/4934.064b787d.chunk.js",
|
||||
"static/js/3518.0ed0b89a.chunk.js": "./static/js/3518.0ed0b89a.chunk.js",
|
||||
"static/js/9942.90927b18.chunk.js": "./static/js/9942.90927b18.chunk.js",
|
||||
"static/js/7021.ad5078e8.chunk.js": "./static/js/7021.ad5078e8.chunk.js",
|
||||
"static/js/2684.b9fc03c6.chunk.js": "./static/js/2684.b9fc03c6.chunk.js",
|
||||
"static/js/6683.fc3f5af3.chunk.js": "./static/js/6683.fc3f5af3.chunk.js",
|
||||
"static/js/8350.a5a279cb.chunk.js": "./static/js/8350.a5a279cb.chunk.js",
|
||||
"static/js/4873.ee12f6f7.chunk.js": "./static/js/4873.ee12f6f7.chunk.js",
|
||||
"static/js/4873.badd008d.chunk.js": "./static/js/4873.badd008d.chunk.js",
|
||||
"static/js/9449.d0d584ad.chunk.js": "./static/js/9449.d0d584ad.chunk.js",
|
||||
"static/js/7659.2d03e3f6.chunk.js": "./static/js/7659.2d03e3f6.chunk.js",
|
||||
"static/js/9968.aff741c4.chunk.js": "./static/js/9968.aff741c4.chunk.js",
|
||||
"static/js/2180.50fad27b.chunk.js": "./static/js/2180.50fad27b.chunk.js",
|
||||
"static/js/8253.18604e19.chunk.js": "./static/js/8253.18604e19.chunk.js",
|
||||
"static/js/3328.cb6f26d0.chunk.js": "./static/js/3328.cb6f26d0.chunk.js",
|
||||
"static/js/1440.427e7e65.chunk.js": "./static/js/1440.427e7e65.chunk.js",
|
||||
"static/js/9179.4b036013.chunk.js": "./static/js/9179.4b036013.chunk.js",
|
||||
"static/js/51.e2978f99.chunk.js": "./static/js/51.e2978f99.chunk.js",
|
||||
"static/js/2180.63708ff1.chunk.js": "./static/js/2180.63708ff1.chunk.js",
|
||||
"static/js/8253.5b2519e1.chunk.js": "./static/js/8253.5b2519e1.chunk.js",
|
||||
"static/js/3328.7229e7d2.chunk.js": "./static/js/3328.7229e7d2.chunk.js",
|
||||
"static/js/1440.f0f58c9c.chunk.js": "./static/js/1440.f0f58c9c.chunk.js",
|
||||
"static/js/9179.07dc687c.chunk.js": "./static/js/9179.07dc687c.chunk.js",
|
||||
"static/js/51.bed0977b.chunk.js": "./static/js/51.bed0977b.chunk.js",
|
||||
"static/js/711.4afa02e3.chunk.js": "./static/js/711.4afa02e3.chunk.js",
|
||||
"static/js/6901.d193e16b.chunk.js": "./static/js/6901.d193e16b.chunk.js",
|
||||
"static/js/2185.2a906448.chunk.js": "./static/js/2185.2a906448.chunk.js",
|
||||
@@ -102,7 +103,7 @@
|
||||
"static/js/2112.dd0b4d48.chunk.js": "./static/js/2112.dd0b4d48.chunk.js",
|
||||
"static/js/4619.aa018cb6.chunk.js": "./static/js/4619.aa018cb6.chunk.js",
|
||||
"static/js/8990.ee4b3da7.chunk.js": "./static/js/8990.ee4b3da7.chunk.js",
|
||||
"static/js/8455.6341f6aa.chunk.js": "./static/js/8455.6341f6aa.chunk.js",
|
||||
"static/js/8455.7978a1cd.chunk.js": "./static/js/8455.7978a1cd.chunk.js",
|
||||
"static/css/3631.e60508f1.chunk.css": "./static/css/3631.e60508f1.chunk.css",
|
||||
"static/js/3631.93134db8.chunk.js": "./static/js/3631.93134db8.chunk.js",
|
||||
"static/js/1604.c298cecf.chunk.js": "./static/js/1604.c298cecf.chunk.js",
|
||||
@@ -148,49 +149,49 @@
|
||||
"static/js/5026.cbf5a1ed.chunk.js": "./static/js/5026.cbf5a1ed.chunk.js",
|
||||
"index.html": "./index.html",
|
||||
"main.90d417ae.css.map": "./static/css/main.90d417ae.css.map",
|
||||
"main.55e03c75.js.map": "./static/js/main.55e03c75.js.map",
|
||||
"main.5f08ae21.js.map": "./static/js/main.5f08ae21.js.map",
|
||||
"2483.64c94bc6.chunk.js.map": "./static/js/2483.64c94bc6.chunk.js.map",
|
||||
"6914.c9671304.chunk.js.map": "./static/js/6914.c9671304.chunk.js.map",
|
||||
"4209.2b6438a1.chunk.js.map": "./static/js/4209.2b6438a1.chunk.js.map",
|
||||
"1829.187799ba.chunk.js.map": "./static/js/1829.187799ba.chunk.js.map",
|
||||
"4455.0849ed40.chunk.js.map": "./static/js/4455.0849ed40.chunk.js.map",
|
||||
"1829.182e4e51.chunk.js.map": "./static/js/1829.182e4e51.chunk.js.map",
|
||||
"4455.a4bf87f3.chunk.js.map": "./static/js/4455.a4bf87f3.chunk.js.map",
|
||||
"5088.60f151ba.chunk.js.map": "./static/js/5088.60f151ba.chunk.js.map",
|
||||
"5140.e9043b63.chunk.js.map": "./static/js/5140.e9043b63.chunk.js.map",
|
||||
"5646.e760211f.chunk.js.map": "./static/js/5646.e760211f.chunk.js.map",
|
||||
"3791.cf2f7179.chunk.js.map": "./static/js/3791.cf2f7179.chunk.js.map",
|
||||
"3176.43953acc.chunk.js.map": "./static/js/3176.43953acc.chunk.js.map",
|
||||
"6137.7c3483b1.chunk.js.map": "./static/js/6137.7c3483b1.chunk.js.map",
|
||||
"7045.ca5a5aae.chunk.js.map": "./static/js/7045.ca5a5aae.chunk.js.map",
|
||||
"9251.43d5879d.chunk.js.map": "./static/js/9251.43d5879d.chunk.js.map",
|
||||
"9251.a72dabc8.chunk.js.map": "./static/js/9251.a72dabc8.chunk.js.map",
|
||||
"2338.8430dcc6.chunk.js.map": "./static/js/2338.8430dcc6.chunk.js.map",
|
||||
"4335.efdb7b8f.chunk.js.map": "./static/js/4335.efdb7b8f.chunk.js.map",
|
||||
"3061.6f255655.chunk.js.map": "./static/js/3061.6f255655.chunk.js.map",
|
||||
"6763.8e2c073b.chunk.js.map": "./static/js/6763.8e2c073b.chunk.js.map",
|
||||
"3543.448be99d.chunk.js.map": "./static/js/3543.448be99d.chunk.js.map",
|
||||
"3061.95077047.chunk.js.map": "./static/js/3061.95077047.chunk.js.map",
|
||||
"6763.8ee776d4.chunk.js.map": "./static/js/6763.8ee776d4.chunk.js.map",
|
||||
"3543.ca7f878f.chunk.js.map": "./static/js/3543.ca7f878f.chunk.js.map",
|
||||
"4061.f26c1196.chunk.js.map": "./static/js/4061.f26c1196.chunk.js.map",
|
||||
"2249.69729722.chunk.js.map": "./static/js/2249.69729722.chunk.js.map",
|
||||
"2249.16ea4e27.chunk.js.map": "./static/js/2249.16ea4e27.chunk.js.map",
|
||||
"9611.c217768e.chunk.js.map": "./static/js/9611.c217768e.chunk.js.map",
|
||||
"2637.2ba50a8f.chunk.js.map": "./static/js/2637.2ba50a8f.chunk.js.map",
|
||||
"380.e60508f1.chunk.css.map": "./static/css/380.e60508f1.chunk.css.map",
|
||||
"380.a147490c.chunk.js.map": "./static/js/380.a147490c.chunk.js.map",
|
||||
"380.878dd1f2.chunk.js.map": "./static/js/380.878dd1f2.chunk.js.map",
|
||||
"5926.e86016db.chunk.js.map": "./static/js/5926.e86016db.chunk.js.map",
|
||||
"701.ffb1c26f.chunk.js.map": "./static/js/701.ffb1c26f.chunk.js.map",
|
||||
"7821.88351a18.chunk.js.map": "./static/js/7821.88351a18.chunk.js.map",
|
||||
"2080.e60508f1.chunk.css.map": "./static/css/2080.e60508f1.chunk.css.map",
|
||||
"2080.2ddaba07.chunk.js.map": "./static/js/2080.2ddaba07.chunk.js.map",
|
||||
"1182.5865af16.chunk.js.map": "./static/js/1182.5865af16.chunk.js.map",
|
||||
"1182.141b8e1c.chunk.js.map": "./static/js/1182.141b8e1c.chunk.js.map",
|
||||
"9033.e60508f1.chunk.css.map": "./static/css/9033.e60508f1.chunk.css.map",
|
||||
"9033.ff414eaf.chunk.js.map": "./static/js/9033.ff414eaf.chunk.js.map",
|
||||
"9033.481de2bd.chunk.js.map": "./static/js/9033.481de2bd.chunk.js.map",
|
||||
"6633.e60508f1.chunk.css.map": "./static/css/6633.e60508f1.chunk.css.map",
|
||||
"6633.b0272e64.chunk.js.map": "./static/js/6633.b0272e64.chunk.js.map",
|
||||
"6633.ba2d9db0.chunk.js.map": "./static/js/6633.ba2d9db0.chunk.js.map",
|
||||
"2731.e60508f1.chunk.css.map": "./static/css/2731.e60508f1.chunk.css.map",
|
||||
"2731.2c59ed4f.chunk.js.map": "./static/js/2731.2c59ed4f.chunk.js.map",
|
||||
"2731.1f028be6.chunk.js.map": "./static/js/2731.1f028be6.chunk.js.map",
|
||||
"5316.e60508f1.chunk.css.map": "./static/css/5316.e60508f1.chunk.css.map",
|
||||
"5316.558355d5.chunk.js.map": "./static/js/5316.558355d5.chunk.js.map",
|
||||
"5316.fda39776.chunk.js.map": "./static/js/5316.fda39776.chunk.js.map",
|
||||
"2555.190c0fbe.chunk.js.map": "./static/js/2555.190c0fbe.chunk.js.map",
|
||||
"7585.dd261b31.chunk.js.map": "./static/js/7585.dd261b31.chunk.js.map",
|
||||
"4847.b6087997.chunk.js.map": "./static/js/4847.b6087997.chunk.js.map",
|
||||
"7585.82cabb9d.chunk.js.map": "./static/js/7585.82cabb9d.chunk.js.map",
|
||||
"4847.3af9af54.chunk.js.map": "./static/js/4847.3af9af54.chunk.js.map",
|
||||
"4653.de61acb4.chunk.js.map": "./static/js/4653.de61acb4.chunk.js.map",
|
||||
"4219.c8ec9d39.chunk.js.map": "./static/js/4219.c8ec9d39.chunk.js.map",
|
||||
"4219.91ab8bc0.chunk.js.map": "./static/js/4219.91ab8bc0.chunk.js.map",
|
||||
"8626.5930d746.chunk.js.map": "./static/js/8626.5930d746.chunk.js.map",
|
||||
"736.99255ac9.chunk.js.map": "./static/js/736.99255ac9.chunk.js.map",
|
||||
"6577.3590592b.chunk.js.map": "./static/js/6577.3590592b.chunk.js.map",
|
||||
@@ -200,19 +201,19 @@
|
||||
"9478.dca1d314.chunk.js.map": "./static/js/9478.dca1d314.chunk.js.map",
|
||||
"7164.3762a0c0.chunk.js.map": "./static/js/7164.3762a0c0.chunk.js.map",
|
||||
"4414.4768f5bb.chunk.js.map": "./static/js/4414.4768f5bb.chunk.js.map",
|
||||
"7798.f7fc00ff.chunk.js.map": "./static/js/7798.f7fc00ff.chunk.js.map",
|
||||
"8833.d59bdcd8.chunk.js.map": "./static/js/8833.d59bdcd8.chunk.js.map",
|
||||
"471.2305812b.chunk.js.map": "./static/js/471.2305812b.chunk.js.map",
|
||||
"7798.7a3790a1.chunk.js.map": "./static/js/7798.7a3790a1.chunk.js.map",
|
||||
"8833.b0a24083.chunk.js.map": "./static/js/8833.b0a24083.chunk.js.map",
|
||||
"471.0c254be3.chunk.js.map": "./static/js/471.0c254be3.chunk.js.map",
|
||||
"483.eb22af68.chunk.js.map": "./static/js/483.eb22af68.chunk.js.map",
|
||||
"9467.fa37a011.chunk.js.map": "./static/js/9467.fa37a011.chunk.js.map",
|
||||
"6895.e4e185e1.chunk.js.map": "./static/js/6895.e4e185e1.chunk.js.map",
|
||||
"7925.565c799d.chunk.js.map": "./static/js/7925.565c799d.chunk.js.map",
|
||||
"5588.5db89ec2.chunk.js.map": "./static/js/5588.5db89ec2.chunk.js.map",
|
||||
"6895.8235fb60.chunk.js.map": "./static/js/6895.8235fb60.chunk.js.map",
|
||||
"7925.c3d5e54d.chunk.js.map": "./static/js/7925.c3d5e54d.chunk.js.map",
|
||||
"5588.41daab44.chunk.js.map": "./static/js/5588.41daab44.chunk.js.map",
|
||||
"4133.1602db5d.chunk.js.map": "./static/js/4133.1602db5d.chunk.js.map",
|
||||
"984.e60508f1.chunk.css.map": "./static/css/984.e60508f1.chunk.css.map",
|
||||
"984.4ead34b2.chunk.js.map": "./static/js/984.4ead34b2.chunk.js.map",
|
||||
"984.78ad4bc3.chunk.js.map": "./static/js/984.78ad4bc3.chunk.js.map",
|
||||
"3956.9b6a6dff.chunk.js.map": "./static/js/3956.9b6a6dff.chunk.js.map",
|
||||
"9076.46bf2c9e.chunk.js.map": "./static/js/9076.46bf2c9e.chunk.js.map",
|
||||
"9076.36a8041b.chunk.js.map": "./static/js/9076.36a8041b.chunk.js.map",
|
||||
"9221.064a4791.chunk.js.map": "./static/js/9221.064a4791.chunk.js.map",
|
||||
"8896.3600ef1f.chunk.js.map": "./static/js/8896.3600ef1f.chunk.js.map",
|
||||
"9134.11ed4367.chunk.js.map": "./static/js/9134.11ed4367.chunk.js.map",
|
||||
@@ -224,24 +225,25 @@
|
||||
"1501.e45e3e8d.chunk.js.map": "./static/js/1501.e45e3e8d.chunk.js.map",
|
||||
"9605.9bcf6af3.chunk.js.map": "./static/js/9605.9bcf6af3.chunk.js.map",
|
||||
"426.8e611cf9.chunk.js.map": "./static/js/426.8e611cf9.chunk.js.map",
|
||||
"4298.90c7e3b7.chunk.js.map": "./static/js/4298.90c7e3b7.chunk.js.map",
|
||||
"2878.a43d663c.chunk.js.map": "./static/js/2878.a43d663c.chunk.js.map",
|
||||
"8495.71a61743.chunk.js.map": "./static/js/8495.71a61743.chunk.js.map",
|
||||
"4934.064b787d.chunk.js.map": "./static/js/4934.064b787d.chunk.js.map",
|
||||
"3518.0ed0b89a.chunk.js.map": "./static/js/3518.0ed0b89a.chunk.js.map",
|
||||
"9942.90927b18.chunk.js.map": "./static/js/9942.90927b18.chunk.js.map",
|
||||
"7021.ad5078e8.chunk.js.map": "./static/js/7021.ad5078e8.chunk.js.map",
|
||||
"2684.b9fc03c6.chunk.js.map": "./static/js/2684.b9fc03c6.chunk.js.map",
|
||||
"6683.fc3f5af3.chunk.js.map": "./static/js/6683.fc3f5af3.chunk.js.map",
|
||||
"8350.a5a279cb.chunk.js.map": "./static/js/8350.a5a279cb.chunk.js.map",
|
||||
"4873.ee12f6f7.chunk.js.map": "./static/js/4873.ee12f6f7.chunk.js.map",
|
||||
"4873.badd008d.chunk.js.map": "./static/js/4873.badd008d.chunk.js.map",
|
||||
"9449.d0d584ad.chunk.js.map": "./static/js/9449.d0d584ad.chunk.js.map",
|
||||
"7659.2d03e3f6.chunk.js.map": "./static/js/7659.2d03e3f6.chunk.js.map",
|
||||
"9968.aff741c4.chunk.js.map": "./static/js/9968.aff741c4.chunk.js.map",
|
||||
"2180.50fad27b.chunk.js.map": "./static/js/2180.50fad27b.chunk.js.map",
|
||||
"8253.18604e19.chunk.js.map": "./static/js/8253.18604e19.chunk.js.map",
|
||||
"3328.cb6f26d0.chunk.js.map": "./static/js/3328.cb6f26d0.chunk.js.map",
|
||||
"1440.427e7e65.chunk.js.map": "./static/js/1440.427e7e65.chunk.js.map",
|
||||
"9179.4b036013.chunk.js.map": "./static/js/9179.4b036013.chunk.js.map",
|
||||
"51.e2978f99.chunk.js.map": "./static/js/51.e2978f99.chunk.js.map",
|
||||
"2180.63708ff1.chunk.js.map": "./static/js/2180.63708ff1.chunk.js.map",
|
||||
"8253.5b2519e1.chunk.js.map": "./static/js/8253.5b2519e1.chunk.js.map",
|
||||
"3328.7229e7d2.chunk.js.map": "./static/js/3328.7229e7d2.chunk.js.map",
|
||||
"1440.f0f58c9c.chunk.js.map": "./static/js/1440.f0f58c9c.chunk.js.map",
|
||||
"9179.07dc687c.chunk.js.map": "./static/js/9179.07dc687c.chunk.js.map",
|
||||
"51.bed0977b.chunk.js.map": "./static/js/51.bed0977b.chunk.js.map",
|
||||
"711.4afa02e3.chunk.js.map": "./static/js/711.4afa02e3.chunk.js.map",
|
||||
"6901.d193e16b.chunk.js.map": "./static/js/6901.d193e16b.chunk.js.map",
|
||||
"2185.2a906448.chunk.js.map": "./static/js/2185.2a906448.chunk.js.map",
|
||||
@@ -249,7 +251,7 @@
|
||||
"2112.dd0b4d48.chunk.js.map": "./static/js/2112.dd0b4d48.chunk.js.map",
|
||||
"4619.aa018cb6.chunk.js.map": "./static/js/4619.aa018cb6.chunk.js.map",
|
||||
"8990.ee4b3da7.chunk.js.map": "./static/js/8990.ee4b3da7.chunk.js.map",
|
||||
"8455.6341f6aa.chunk.js.map": "./static/js/8455.6341f6aa.chunk.js.map",
|
||||
"8455.7978a1cd.chunk.js.map": "./static/js/8455.7978a1cd.chunk.js.map",
|
||||
"3631.e60508f1.chunk.css.map": "./static/css/3631.e60508f1.chunk.css.map",
|
||||
"3631.93134db8.chunk.js.map": "./static/js/3631.93134db8.chunk.js.map",
|
||||
"1604.c298cecf.chunk.js.map": "./static/js/1604.c298cecf.chunk.js.map",
|
||||
@@ -296,6 +298,6 @@
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.90d417ae.css",
|
||||
"static/js/main.55e03c75.js"
|
||||
"static/js/main.5f08ae21.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.55e03c75.js"></script><link href="./static/css/main.90d417ae.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.5f08ae21.js"></script><link href="./static/css/main.90d417ae.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
2
portal-ui/build/static/js/1182.141b8e1c.chunk.js
Normal file
2
portal-ui/build/static/js/1182.141b8e1c.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/1182.141b8e1c.chunk.js.map
Normal file
1
portal-ui/build/static/js/1182.141b8e1c.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/1440.f0f58c9c.chunk.js
Normal file
2
portal-ui/build/static/js/1440.f0f58c9c.chunk.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/1829.182e4e51.chunk.js
Normal file
2
portal-ui/build/static/js/1829.182e4e51.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/1829.182e4e51.chunk.js.map
Normal file
1
portal-ui/build/static/js/1829.182e4e51.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/2180.63708ff1.chunk.js
Normal file
2
portal-ui/build/static/js/2180.63708ff1.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/2180.63708ff1.chunk.js.map
Normal file
1
portal-ui/build/static/js/2180.63708ff1.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/2249.16ea4e27.chunk.js
Normal file
2
portal-ui/build/static/js/2249.16ea4e27.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/2249.16ea4e27.chunk.js.map
Normal file
1
portal-ui/build/static/js/2249.16ea4e27.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/2731.1f028be6.chunk.js
Normal file
2
portal-ui/build/static/js/2731.1f028be6.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/2731.1f028be6.chunk.js.map
Normal file
1
portal-ui/build/static/js/2731.1f028be6.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/3061.95077047.chunk.js
Normal file
2
portal-ui/build/static/js/3061.95077047.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/3061.95077047.chunk.js.map
Normal file
1
portal-ui/build/static/js/3061.95077047.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/3328.7229e7d2.chunk.js
Normal file
2
portal-ui/build/static/js/3328.7229e7d2.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/3328.7229e7d2.chunk.js.map
Normal file
1
portal-ui/build/static/js/3328.7229e7d2.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/3543.ca7f878f.chunk.js.map
Normal file
1
portal-ui/build/static/js/3543.ca7f878f.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/3791.cf2f7179.chunk.js
Normal file
2
portal-ui/build/static/js/3791.cf2f7179.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/3791.cf2f7179.chunk.js.map
Normal file
1
portal-ui/build/static/js/3791.cf2f7179.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/380.878dd1f2.chunk.js.map
Normal file
1
portal-ui/build/static/js/380.878dd1f2.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/4219.91ab8bc0.chunk.js.map
Normal file
1
portal-ui/build/static/js/4219.91ab8bc0.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/4298.90c7e3b7.chunk.js
Normal file
2
portal-ui/build/static/js/4298.90c7e3b7.chunk.js
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";(self.webpackChunkportal_ui=self.webpackChunkportal_ui||[]).push([[4298],{24298:function(e,n,t){t.r(n);var r=t(29439),a=t(1413),o=t(72791),s=t(60364),i=t(11135),c=t(25787),u=t(23814),l=t(81207),Z=t(39281),d=t(10703),f=t(79836),p=t(56890),h=t(35855),m=t(53994),v=t(53382),x=t(80184);n.default=(0,c.Z)((function(e){return(0,i.Z)((0,a.Z)((0,a.Z)((0,a.Z)((0,a.Z)({tableWrapper:{height:"450px"}},u.OR),u.qg),u.VX),(0,u.Bz)(e.spacing(4))))}))((function(e){var n=e.classes,t=e.match,a=e.loadingTenant,i=e.setErrorSnackMessage,c=(0,o.useState)(!0),u=(0,r.Z)(c,2),j=u[0],b=u[1],g=t.params.tenantName,T=t.params.tenantNamespace,N=(0,o.useState)([""]),w=(0,r.Z)(N,1)[0],M=(0,o.useState)([""]),S=(0,r.Z)(M,1)[0],R=(0,o.useState)([""]),C=(0,r.Z)(R,1)[0],k=(0,s.I0)();return(0,o.useEffect)((function(){a&&b(!0)}),[a]),(0,o.useEffect)((function(){j&&l.Z.invoke("GET","/api/v1/namespaces/".concat(T,"/tenants/").concat(g,"/csr")).then((function(e){for(var n=0;n<e.csrElement.length;n++){var t=e.csrElement[n];w.push(t.status),S.push(t.name),C.push(t.annotations)}b(!1)})).catch((function(e){k(i(e))}))}),[j,T,g,i,C,S,w,k]),(0,x.jsxs)(o.Fragment,{children:[(0,x.jsx)("h1",{className:n.sectionTitle,children:"Certificate Signing Requests"}),(0,x.jsx)(Z.Z,{component:d.Z,children:(0,x.jsxs)(f.Z,{"aria-label":"collapsible table",children:[(0,x.jsx)(p.Z,{children:(0,x.jsxs)(h.Z,{children:[(0,x.jsx)(m.Z,{children:"Name"}),(0,x.jsx)(m.Z,{children:"Status"}),(0,x.jsx)(m.Z,{children:"Annotation"}),(0,x.jsx)(m.Z,{})]})}),(0,x.jsx)(v.Z,{children:(0,x.jsxs)(h.Z,{children:[(0,x.jsx)(m.Z,{children:S.map((function(e){return(0,x.jsx)("p",{children:e})}))}),(0,x.jsx)(m.Z,{children:w.map((function(e){return(0,x.jsx)("p",{children:e})}))}),(0,x.jsx)(m.Z,{children:C.map((function(e){return(0,x.jsx)("p",{children:e})}))})]})})]})})]})}))},39281:function(e,n,t){t.d(n,{Z:function(){return h}});var r=t(87462),a=t(63366),o=t(72791),s=t(28182),i=t(90767),c=t(93736),u=t(47630),l=t(95159);function Z(e){return(0,l.Z)("MuiTableContainer",e)}(0,t(30208).Z)("MuiTableContainer",["root"]);var d=t(80184),f=["className","component"],p=(0,u.ZP)("div",{name:"MuiTableContainer",slot:"Root",overridesResolver:function(e,n){return n.root}})({width:"100%",overflowX:"auto"}),h=o.forwardRef((function(e,n){var t=(0,c.Z)({props:e,name:"MuiTableContainer"}),o=t.className,u=t.component,l=void 0===u?"div":u,h=(0,a.Z)(t,f),m=(0,r.Z)({},t,{component:l}),v=function(e){var n=e.classes;return(0,i.Z)({root:["root"]},Z,n)}(m);return(0,d.jsx)(p,(0,r.Z)({ref:n,as:l,className:(0,s.Z)(v.root,o),ownerState:m},h))}))},56890:function(e,n,t){t.d(n,{Z:function(){return x}});var r=t(87462),a=t(63366),o=t(72791),s=t(28182),i=t(90767),c=t(829),u=t(93736),l=t(47630),Z=t(95159);function d(e){return(0,Z.Z)("MuiTableHead",e)}(0,t(30208).Z)("MuiTableHead",["root"]);var f=t(80184),p=["className","component"],h=(0,l.ZP)("thead",{name:"MuiTableHead",slot:"Root",overridesResolver:function(e,n){return n.root}})({display:"table-header-group"}),m={variant:"head"},v="thead",x=o.forwardRef((function(e,n){var t=(0,u.Z)({props:e,name:"MuiTableHead"}),o=t.className,l=t.component,Z=void 0===l?v:l,x=(0,a.Z)(t,p),j=(0,r.Z)({},t,{component:Z}),b=function(e){var n=e.classes;return(0,i.Z)({root:["root"]},d,n)}(j);return(0,f.jsx)(c.Z.Provider,{value:m,children:(0,f.jsx)(h,(0,r.Z)({as:Z,className:(0,s.Z)(b.root,o),ref:n,role:Z===v?null:"rowgroup",ownerState:j},x))})}))}}]);
|
||||
//# sourceMappingURL=4298.90c7e3b7.chunk.js.map
|
||||
1
portal-ui/build/static/js/4298.90c7e3b7.chunk.js.map
Normal file
1
portal-ui/build/static/js/4298.90c7e3b7.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/4455.a4bf87f3.chunk.js
Normal file
2
portal-ui/build/static/js/4455.a4bf87f3.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/4455.a4bf87f3.chunk.js.map
Normal file
1
portal-ui/build/static/js/4455.a4bf87f3.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/471.0c254be3.chunk.js
Normal file
2
portal-ui/build/static/js/471.0c254be3.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/471.0c254be3.chunk.js.map
Normal file
1
portal-ui/build/static/js/471.0c254be3.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/4847.3af9af54.chunk.js.map
Normal file
1
portal-ui/build/static/js/4847.3af9af54.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/4873.badd008d.chunk.js.map
Normal file
1
portal-ui/build/static/js/4873.badd008d.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/51.bed0977b.chunk.js
Normal file
2
portal-ui/build/static/js/51.bed0977b.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/51.bed0977b.chunk.js.map
Normal file
1
portal-ui/build/static/js/51.bed0977b.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/5316.fda39776.chunk.js
Normal file
2
portal-ui/build/static/js/5316.fda39776.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/5316.fda39776.chunk.js.map
Normal file
1
portal-ui/build/static/js/5316.fda39776.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/5588.41daab44.chunk.js
Normal file
2
portal-ui/build/static/js/5588.41daab44.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/5588.41daab44.chunk.js.map
Normal file
1
portal-ui/build/static/js/5588.41daab44.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user