Compare commits
93 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78fa499c12 | ||
|
|
e03d483d33 | ||
|
|
2cc41d56a0 | ||
|
|
99715ff076 | ||
|
|
9c3e8f5bf7 | ||
|
|
21158e6c7a | ||
|
|
725d6f9691 | ||
|
|
dd488e4f7a | ||
|
|
3b2c740fe0 | ||
|
|
db5ae3e09f | ||
|
|
8a79409ef6 | ||
|
|
9444dadc16 | ||
|
|
5618e08bbe | ||
|
|
f4001c0add | ||
|
|
02c4910044 | ||
|
|
1713e58e62 | ||
|
|
90b33bb88f | ||
|
|
48dfe74aed | ||
|
|
9b39566f7c | ||
|
|
aba7a9e1c9 | ||
|
|
3db22a2479 | ||
|
|
884321cfce | ||
|
|
20c07a22e3 | ||
|
|
bf126d3a84 | ||
|
|
1e59f131e8 | ||
|
|
dfcd49bb5d | ||
|
|
a7ab26c81e | ||
|
|
35855daa12 | ||
|
|
3ce0b3d633 | ||
|
|
569d2390b9 | ||
|
|
a39e468b96 | ||
|
|
bbc47e6e11 | ||
|
|
4fb8c2f684 | ||
|
|
65dcdc674a | ||
|
|
ebc2b208d2 | ||
|
|
b29fc0993b | ||
|
|
a3d0cb37a3 | ||
|
|
85d549cc51 | ||
|
|
5f46ec2541 | ||
|
|
9db0c358a4 | ||
|
|
eefc6a7894 | ||
|
|
c529a6d127 | ||
|
|
347c6aba3b | ||
|
|
400892565d | ||
|
|
b9873fa471 | ||
|
|
62fe583a21 | ||
|
|
a69f597f43 | ||
|
|
cdb4392633 | ||
|
|
41f77f128e | ||
|
|
af68a0c7e4 | ||
|
|
0ea2193878 | ||
|
|
06b08593b7 | ||
|
|
6b3ff10027 | ||
|
|
53d278a91e | ||
|
|
820fa61b43 | ||
|
|
3f60df9071 | ||
|
|
0bbd4f0282 | ||
|
|
1fa4d19e93 | ||
|
|
f56b4905c9 | ||
|
|
575bf2927d | ||
|
|
6bacd0a45c | ||
|
|
7f5de2d70e | ||
|
|
f0d5398748 | ||
|
|
813458c4c1 | ||
|
|
aae493ac82 | ||
|
|
f5234d2830 | ||
|
|
f6acb888d2 | ||
|
|
5328f53943 | ||
|
|
70a4d76283 | ||
|
|
373bfbfe3f | ||
|
|
b8417fb7a0 | ||
|
|
70845c0ec5 | ||
|
|
21a9073c5e | ||
|
|
ad240d2ec5 | ||
|
|
2b34fbae47 | ||
|
|
258a9400d9 | ||
|
|
33f13c4853 | ||
|
|
000071e414 | ||
|
|
3638455abb | ||
|
|
8102ab7e35 | ||
|
|
34dc51a579 | ||
|
|
0086aa8f64 | ||
|
|
abd9768bd9 | ||
|
|
0e778a7466 | ||
|
|
fae0135f69 | ||
|
|
3b69d9809e | ||
|
|
09a5dfebbc | ||
|
|
9a01922c67 | ||
|
|
6df6d785d7 | ||
|
|
e82103c678 | ||
|
|
c2f0889ff8 | ||
|
|
4a8ec219cc | ||
|
|
e461a2268a |
2
.github/workflows/compiles.yml
vendored
2
.github/workflows/compiles.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/crosscompile-1.yml
vendored
2
.github/workflows/crosscompile-1.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/crosscompile-2.yml
vendored
2
.github/workflows/crosscompile-2.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/crosscompile-3.yml
vendored
2
.github/workflows/crosscompile-3.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/crosscompile-4.yml
vendored
2
.github/workflows/crosscompile-4.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/crosscompile-5.yml
vendored
2
.github/workflows/crosscompile-5.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/go-test-pkg.yml
vendored
2
.github/workflows/go-test-pkg.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x, 1.17.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
25
.github/workflows/integration.yml
vendored
25
.github/workflows/integration.yml
vendored
@@ -8,14 +8,21 @@ on:
|
||||
branches:
|
||||
- master
|
||||
|
||||
# This ensures that previous jobs for the PR are canceled when the PR is
|
||||
# updated.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
minio-test:
|
||||
name: Integration Tests with Latest Distributed MinIO
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x]
|
||||
os: [ubuntu-latest]
|
||||
go-version: [1.17.x]
|
||||
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
uses: actions/setup-go@v2
|
||||
@@ -27,13 +34,5 @@ jobs:
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build on ${{ matrix.os }}
|
||||
env:
|
||||
GO111MODULE: on
|
||||
GOOS: linux
|
||||
CGO_ENABLED: 0
|
||||
run: |
|
||||
wget -O /tmp/minio https://dl.minio.io/server/minio/release/linux-amd64/minio
|
||||
chmod +x /tmp/minio
|
||||
mkdir -p /tmp/certs-dir
|
||||
/tmp/minio server --quiet -S /tmp/certs-dir /tmp/fs{1...4} &
|
||||
go test github.com/minio/console/integration/...
|
||||
make test-integration
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.16.x, 1.17.x]
|
||||
go-version: [1.17.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
|
||||
|
||||
5
Makefile
5
Makefile
@@ -63,6 +63,11 @@ swagger-operator:
|
||||
assets:
|
||||
@(cd portal-ui; yarn install; make build-static; yarn prettier --write . --loglevel warn; cd ..)
|
||||
|
||||
test-integration:
|
||||
@(docker run -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4} && sleep 5)
|
||||
@(GO111MODULE=on go test -race -v github.com/minio/console/integration/...)
|
||||
@(docker stop minio)
|
||||
|
||||
test:
|
||||
@(GO111MODULE=on go test -race -v github.com/minio/console/restapi/...)
|
||||
|
||||
|
||||
@@ -53,12 +53,12 @@ docker pull minio/console
|
||||
```
|
||||
|
||||
### Build from source
|
||||
> You will need a working Go environment. Therefore, please follow [How to install Go](https://golang.org/doc/install).
|
||||
> Minimum version required is go1.17
|
||||
|
||||
```
|
||||
GO111MODULE=on go install github.com/minio/console/cmd/console@latest
|
||||
go install github.com/minio/console/cmd/console@latest
|
||||
```
|
||||
> You will need a working Go environment. Therefore, please follow [How to install Go](https://golang.org/doc/install).
|
||||
> Minimum version required is go1.16
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/minio/console/restapi"
|
||||
@@ -173,6 +174,10 @@ func loadOperatorAllCerts(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if restapi.GlobalTLSCertsManager != nil {
|
||||
restapi.GlobalTLSCertsManager.ReloadOnSignal(syscall.SIGHUP)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
@@ -172,6 +173,10 @@ func loadAllCerts(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
if restapi.GlobalTLSCertsManager != nil {
|
||||
restapi.GlobalTLSCertsManager.ReloadOnSignal(syscall.SIGHUP)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
125
go.mod
125
go.mod
@@ -1,6 +1,6 @@
|
||||
module github.com/minio/console
|
||||
|
||||
go 1.16
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
@@ -13,18 +13,19 @@ require (
|
||||
github.com/go-openapi/strfmt v0.20.0
|
||||
github.com/go-openapi/swag v0.19.14
|
||||
github.com/go-openapi/validate v0.20.2
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jessevdk/go-flags v1.4.0
|
||||
github.com/klauspost/compress v1.13.6
|
||||
github.com/minio/cli v1.22.0
|
||||
github.com/minio/direct-csi v1.3.5-0.20210601185811-f7776f7961bf
|
||||
github.com/minio/kes v0.11.0
|
||||
github.com/minio/madmin-go v1.1.10
|
||||
github.com/minio/mc v0.0.0-20211027024940-7866f97ef502
|
||||
github.com/minio/minio-go/v7 v7.0.15-0.20211004160302-3b57c1e369ca
|
||||
github.com/minio/madmin-go v1.1.17
|
||||
github.com/minio/mc v0.0.0-20211207230606-23a05f5a17f2
|
||||
github.com/minio/minio-go/v7 v7.0.17
|
||||
github.com/minio/operator v0.0.0-20211011212245-31460bbbc4b7
|
||||
github.com/minio/operator/logsearchapi v0.0.0-20211011212245-31460bbbc4b7
|
||||
github.com/minio/pkg v1.1.5
|
||||
github.com/minio/pkg v1.1.9
|
||||
github.com/minio/selfupdate v0.3.1
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/rs/xid v1.3.0
|
||||
@@ -32,7 +33,7 @@ require (
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/unrolled/secure v1.0.9
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.21.1
|
||||
@@ -40,4 +41,116 @@ require (
|
||||
k8s.io/client-go v0.21.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/VividCortex/ewma v1.1.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/briandowns/spinner v1.16.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cheggaaa/pb v1.0.29 // indirect
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/evanphx/json-patch v4.9.0+incompatible // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/georgysavva/scany v0.2.7 // indirect
|
||||
github.com/go-logr/logr v0.4.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-openapi/analysis v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/goccy/go-json v0.7.9 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.5 // indirect
|
||||
github.com/google/gofuzz v1.1.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/gnostic v0.5.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.0 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.0 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.1 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.7 // indirect
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.10 // indirect
|
||||
github.com/mattn/go-ieproxy v0.0.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mb0/glob v0.0.0-20160210091149-1eb79d2de6c4 // indirect
|
||||
github.com/minio/argon2 v1.0.0 // indirect
|
||||
github.com/minio/colorjson v1.0.1 // indirect
|
||||
github.com/minio/filepath v1.0.0 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/philhofer/fwd v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pkg/profile v1.6.0 // indirect
|
||||
github.com/pkg/xattr v0.4.3 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.31.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rjeczalik/notify v0.9.2 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.21.8 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/tidwall/gjson v1.10.2 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tinylib/msgp v1.1.6 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.0 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.4.6 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.19.1 // indirect
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
|
||||
google.golang.org/appengine v1.6.6 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 // indirect
|
||||
google.golang.org/grpc v1.41.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/h2non/filetype.v1 v1.0.5 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.63.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/klog/v2 v2.8.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 // indirect
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect
|
||||
maze.io/x/duration v0.0.0-20160924141736-faac084b6075 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.8.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
)
|
||||
|
||||
replace google.golang.org/grpc => google.golang.org/grpc v1.29.1
|
||||
|
||||
32
go.sum
32
go.sum
@@ -325,8 +325,9 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
|
||||
github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
||||
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
@@ -487,6 +488,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0=
|
||||
github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -676,6 +679,7 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
@@ -909,16 +913,18 @@ github.com/minio/filepath v1.0.0/go.mod h1:/nRZA2ldl5z6jT9/KQuvZcQlxZIMQoFFQPvEX
|
||||
github.com/minio/kes v0.11.0 h1:8ma6OCVSxKT50b1uYXLJro3m7PmZtCLxBaTddQexI5k=
|
||||
github.com/minio/kes v0.11.0/go.mod h1:mTF1Bv8YVEtQqF/B7Felp4tLee44Pp+dgI0rhCvgNg8=
|
||||
github.com/minio/madmin-go v1.0.12/go.mod h1:BK+z4XRx7Y1v8SFWXsuLNqQqnq5BO/axJ8IDJfgyvfs=
|
||||
github.com/minio/madmin-go v1.1.10 h1:pfMgXkzdwADnNfVdNMJbwok2fjb2sJ7Q76kDt89RGzE=
|
||||
github.com/minio/madmin-go v1.1.10/go.mod h1:Iu0OnrMWNBYx1lqJTW+BFjBMx0Hi0wjw8VmqhiOs2Jo=
|
||||
github.com/minio/mc v0.0.0-20211027024940-7866f97ef502 h1:7ip9qTspUniv+WDENgOcfUr95IccxG5aDkBM4Z96kQg=
|
||||
github.com/minio/mc v0.0.0-20211027024940-7866f97ef502/go.mod h1:vxztwXLB9Gyl/h3Yh08Mpz1CB/0FO5Es0iQRpzxvS5I=
|
||||
github.com/minio/madmin-go v1.1.15/go.mod h1:Iu0OnrMWNBYx1lqJTW+BFjBMx0Hi0wjw8VmqhiOs2Jo=
|
||||
github.com/minio/madmin-go v1.1.17 h1:P7my58nSulXawjixhS4S2pT43+3M+Y0P7M43I3YdzGo=
|
||||
github.com/minio/madmin-go v1.1.17/go.mod h1:Iu0OnrMWNBYx1lqJTW+BFjBMx0Hi0wjw8VmqhiOs2Jo=
|
||||
github.com/minio/mc v0.0.0-20211207230606-23a05f5a17f2 h1:xocb1RGyrDJ8PxkNn0NSbaBlfdU6J/Ag9QK62pb7nR8=
|
||||
github.com/minio/mc v0.0.0-20211207230606-23a05f5a17f2/go.mod h1:siI9jWTzj1KsNXgz6NOL/S7OTaAUM0OMi+zEkF08gnA=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.11-0.20210302210017-6ae69c73ce78/go.mod h1:mTh2uJuAbEqdhMVl6CMIIZLUeiMiWtJR4JB8/5g2skw=
|
||||
github.com/minio/minio-go/v7 v7.0.15-0.20211004160302-3b57c1e369ca h1:DKdUaXCMM6fFUwS9K68HGw8nlqqUZhQN106rPW1V/oI=
|
||||
github.com/minio/minio-go/v7 v7.0.15-0.20211004160302-3b57c1e369ca/go.mod h1:pUV0Pc+hPd1nccgmzQF/EXh48l/Z/yps6QPF1aaie4g=
|
||||
github.com/minio/minio-go/v7 v7.0.16-0.20211108161804-a7a36ee131df/go.mod h1:pUV0Pc+hPd1nccgmzQF/EXh48l/Z/yps6QPF1aaie4g=
|
||||
github.com/minio/minio-go/v7 v7.0.17 h1:5SiS3pqiQDbNhmXMxtqn2HzAInbN5cbHT7ip9F0F07E=
|
||||
github.com/minio/minio-go/v7 v7.0.17/go.mod h1:SyQ1IFeJuaa+eV5yEDxW7hYE1s5VVq5sgImDe27R+zg=
|
||||
github.com/minio/operator v0.0.0-20211011212245-31460bbbc4b7 h1:dkfuMNslMjGoJ4ArAMSoQhidYNdm3SgzLBP+f96O3/E=
|
||||
github.com/minio/operator v0.0.0-20211011212245-31460bbbc4b7/go.mod h1:lDpuz8nwsfhKlfiBaA3Z8AW019fWEAjO2gltfLbdorE=
|
||||
github.com/minio/operator/logsearchapi v0.0.0-20211011212245-31460bbbc4b7 h1:vFtQqCt67ETp0JAkOKRWTKkgwFv14Vc1jJSxmQ8wJE0=
|
||||
@@ -927,8 +933,8 @@ github.com/minio/pkg v1.0.3/go.mod h1:obU54TZ9QlMv0TRaDgQ/JTzf11ZSXxnSfLrm4tMtBP
|
||||
github.com/minio/pkg v1.0.4/go.mod h1:obU54TZ9QlMv0TRaDgQ/JTzf11ZSXxnSfLrm4tMtBP8=
|
||||
github.com/minio/pkg v1.0.11/go.mod h1:32x/3OmGB0EOi1N+3ggnp+B5VFkSBBB9svPMVfpnf14=
|
||||
github.com/minio/pkg v1.1.3/go.mod h1:32x/3OmGB0EOi1N+3ggnp+B5VFkSBBB9svPMVfpnf14=
|
||||
github.com/minio/pkg v1.1.5 h1:phwKkJBQdVLyxOXC3RChPVGLtebplzQJ5jJ3l/HBvnk=
|
||||
github.com/minio/pkg v1.1.5/go.mod h1:32x/3OmGB0EOi1N+3ggnp+B5VFkSBBB9svPMVfpnf14=
|
||||
github.com/minio/pkg v1.1.9 h1:NJrcrQyFCSgyF+u6v7FbPXjjNV0oSnBuBevhsTKmA2U=
|
||||
github.com/minio/pkg v1.1.9/go.mod h1:32x/3OmGB0EOi1N+3ggnp+B5VFkSBBB9svPMVfpnf14=
|
||||
github.com/minio/selfupdate v0.3.1 h1:BWEFSNnrZVMUWXbXIgLDNDjbejkmpAmZvy/nCz1HlEs=
|
||||
github.com/minio/selfupdate v0.3.1/go.mod h1:b8ThJzzH7u2MkF6PcIra7KaXO9Khf6alWPvMSyTDCFM=
|
||||
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
@@ -1467,8 +1473,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
|
||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1575,8 +1581,8 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
|
||||
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="16.986" viewBox="0 0 17 16.986">
|
||||
<g id="Tools" transform="translate(-56.747 -82.596)">
|
||||
<g id="Grupo_1868" data-name="Grupo 1868">
|
||||
<path id="Trazado_6843" data-name="Trazado 6843" d="M71.847,82.6,68.6,84.36l.016.961-2.387,2.387,2.411,2.411,2.42-2.42.871,0,1.82-3.206Z" fill="#bccee6"/>
|
||||
<path id="Trazado_6844" data-name="Trazado 6844" d="M61.539,92.4l-4.525,4.525a.852.852,0,0,0,0,1.205l1.205,1.206a.853.853,0,0,0,1.206,0l4.524-4.525Z" fill="#bccee6"/>
|
||||
</g>
|
||||
<path id="Trazado_6845" data-name="Trazado 6845" d="M73.162,96.921l-9.736-9.735a3.381,3.381,0,0,0-4.152-4.153L61.343,85.1l-2.411,2.411-2.069-2.069A3.381,3.381,0,0,0,61.016,89.6l9.735,9.736a.853.853,0,0,0,1.206,0l1.205-1.206A.852.852,0,0,0,73.162,96.921Z" fill="#bccee6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 828 B |
BIN
images/pic1.png
BIN
images/pic1.png
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.8 MiB |
BIN
images/pic2.png
BIN
images/pic2.png
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.8 MiB |
@@ -123,16 +123,17 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
||||
|
||||
loginResponse := models.LoginResponse{}
|
||||
err = json.Unmarshal(bodyBytes, &loginResponse)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
for _, cookie := range response.Cookies() {
|
||||
if cookie.Name == "token" {
|
||||
token = cookie.Value
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
token = loginResponse.SessionID
|
||||
|
||||
if token == "" {
|
||||
log.Println("authentication token not found in cookies response")
|
||||
return
|
||||
}
|
||||
|
||||
code := m.Run()
|
||||
@@ -207,6 +208,153 @@ func TestAddBucket(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBucket(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: 2 * time.Second,
|
||||
}
|
||||
|
||||
requestDataAdd := map[string]interface{}{
|
||||
"name": "test3",
|
||||
"versioning": false,
|
||||
"locking": false,
|
||||
}
|
||||
|
||||
requestDataJSON, _ := json.Marshal(requestDataAdd)
|
||||
|
||||
requestDataBody := bytes.NewReader(requestDataJSON)
|
||||
|
||||
// put bucket
|
||||
request, err := http.NewRequest("POST", "http://localhost:9090/api/v1/buckets", 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)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// get bucket
|
||||
request, err = http.NewRequest("GET", "http://localhost:9090/api/v1/buckets/test3", 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)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
if response != nil {
|
||||
assert.Equal(200, response.StatusCode, "Status Code is incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetBucketTags(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: 2 * time.Second,
|
||||
}
|
||||
|
||||
requestDataAdd := map[string]interface{}{
|
||||
"name": "test4",
|
||||
"versioning": false,
|
||||
"locking": false,
|
||||
}
|
||||
|
||||
requestDataJSON, _ := json.Marshal(requestDataAdd)
|
||||
|
||||
requestDataBody := bytes.NewReader(requestDataJSON)
|
||||
|
||||
// put bucket
|
||||
request, err := http.NewRequest("POST", "http://localhost:9090/api/v1/buckets", requestDataBody)
|
||||
request.Close = true
|
||||
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)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
requestDataTags := map[string]interface{}{
|
||||
"tags": map[string]interface{}{
|
||||
"test": "TAG",
|
||||
},
|
||||
}
|
||||
|
||||
requestTagsJSON, _ := json.Marshal(requestDataTags)
|
||||
|
||||
requestTagsBody := bytes.NewBuffer(requestTagsJSON)
|
||||
|
||||
request, err = http.NewRequest(http.MethodPut, "http://localhost:9090/api/v1/buckets/test4/tags", requestTagsBody)
|
||||
request.Close = true
|
||||
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)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// get bucket
|
||||
request, err = http.NewRequest("GET", "http://localhost:9090/api/v1/buckets/test4", nil)
|
||||
request.Close = true
|
||||
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)
|
||||
assert.Nil(err)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
||||
|
||||
bucket := models.Bucket{}
|
||||
err = json.Unmarshal(bodyBytes, &bucket)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
assert.Equal("TAG", bucket.Details.Tags["test"], "Failed to add tag")
|
||||
}
|
||||
|
||||
func TestBucketVersioning(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ spec:
|
||||
serviceAccountName: console-sa
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.12.2
|
||||
image: minio/console:v0.12.9
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_OPERATOR_MODE
|
||||
|
||||
@@ -32,7 +32,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: console
|
||||
image: minio/console:v0.12.2
|
||||
image: minio/console:v0.12.9
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
env:
|
||||
- name: CONSOLE_MINIO_SERVER
|
||||
|
||||
@@ -42,6 +42,9 @@ type AdminInfoResponse struct {
|
||||
// objects
|
||||
Objects int64 `json:"objects,omitempty"`
|
||||
|
||||
// prometheus not ready
|
||||
PrometheusNotReady bool `json:"prometheusNotReady,omitempty"`
|
||||
|
||||
// servers
|
||||
Servers []*ServerProperties `json:"servers"`
|
||||
|
||||
|
||||
165
models/allocatable_resources_response.go
Normal file
165
models/allocatable_resources_response.go
Normal file
@@ -0,0 +1,165 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 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/errors"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// AllocatableResourcesResponse allocatable resources response
|
||||
//
|
||||
// swagger:model allocatableResourcesResponse
|
||||
type AllocatableResourcesResponse struct {
|
||||
|
||||
// cpu priority
|
||||
CPUPriority *NodeMaxAllocatableResources `json:"cpu_priority,omitempty"`
|
||||
|
||||
// mem priority
|
||||
MemPriority *NodeMaxAllocatableResources `json:"mem_priority,omitempty"`
|
||||
|
||||
// min allocatable cpu
|
||||
MinAllocatableCPU int64 `json:"min_allocatable_cpu,omitempty"`
|
||||
|
||||
// min allocatable mem
|
||||
MinAllocatableMem int64 `json:"min_allocatable_mem,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this allocatable resources response
|
||||
func (m *AllocatableResourcesResponse) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateCPUPriority(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateMemPriority(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) validateCPUPriority(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.CPUPriority) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.CPUPriority != nil {
|
||||
if err := m.CPUPriority.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("cpu_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) validateMemPriority(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.MemPriority) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.MemPriority != nil {
|
||||
if err := m.MemPriority.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("mem_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this allocatable resources response based on the context it is used
|
||||
func (m *AllocatableResourcesResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidateCPUPriority(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.contextValidateMemPriority(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) contextValidateCPUPriority(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.CPUPriority != nil {
|
||||
if err := m.CPUPriority.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("cpu_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AllocatableResourcesResponse) contextValidateMemPriority(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.MemPriority != nil {
|
||||
if err := m.MemPriority.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("mem_priority")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *AllocatableResourcesResponse) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *AllocatableResourcesResponse) UnmarshalBinary(b []byte) error {
|
||||
var res AllocatableResourcesResponse
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -40,18 +40,12 @@ type Bucket struct {
|
||||
// access
|
||||
Access *BucketAccess `json:"access,omitempty"`
|
||||
|
||||
// allowed actions
|
||||
AllowedActions []string `json:"allowedActions"`
|
||||
|
||||
// creation date
|
||||
CreationDate string `json:"creation_date,omitempty"`
|
||||
|
||||
// details
|
||||
Details *BucketDetails `json:"details,omitempty"`
|
||||
|
||||
// manage
|
||||
Manage bool `json:"manage,omitempty"`
|
||||
|
||||
// name
|
||||
// Required: true
|
||||
// Min Length: 3
|
||||
|
||||
67
models/metadata.go
Normal file
67
models/metadata.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) 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 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"
|
||||
)
|
||||
|
||||
// Metadata metadata
|
||||
//
|
||||
// swagger:model metadata
|
||||
type Metadata struct {
|
||||
|
||||
// object metadata
|
||||
ObjectMetadata interface{} `json:"objectMetadata,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this metadata
|
||||
func (m *Metadata) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this metadata based on context it is used
|
||||
func (m *Metadata) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *Metadata) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *Metadata) UnmarshalBinary(b []byte) error {
|
||||
var res Metadata
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
70
models/node_max_allocatable_resources.go
Normal file
70
models/node_max_allocatable_resources.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) 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 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"
|
||||
)
|
||||
|
||||
// NodeMaxAllocatableResources node max allocatable resources
|
||||
//
|
||||
// swagger:model nodeMaxAllocatableResources
|
||||
type NodeMaxAllocatableResources struct {
|
||||
|
||||
// max allocatable cpu
|
||||
MaxAllocatableCPU int64 `json:"max_allocatable_cpu,omitempty"`
|
||||
|
||||
// max allocatable mem
|
||||
MaxAllocatableMem int64 `json:"max_allocatable_mem,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this node max allocatable resources
|
||||
func (m *NodeMaxAllocatableResources) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this node max allocatable resources based on context it is used
|
||||
func (m *NodeMaxAllocatableResources) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *NodeMaxAllocatableResources) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *NodeMaxAllocatableResources) UnmarshalBinary(b []byte) error {
|
||||
var res NodeMaxAllocatableResources
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -37,14 +37,11 @@ import (
|
||||
// swagger:model operatorSessionResponse
|
||||
type OperatorSessionResponse struct {
|
||||
|
||||
// features
|
||||
Features []string `json:"features"`
|
||||
|
||||
// operator
|
||||
Operator bool `json:"operator,omitempty"`
|
||||
|
||||
// pages
|
||||
Pages []string `json:"pages"`
|
||||
// permissions
|
||||
Permissions map[string][]string `json:"permissions,omitempty"`
|
||||
|
||||
// status
|
||||
// Enum: [ok]
|
||||
|
||||
67
models/put_bucket_tags_request.go
Normal file
67
models/put_bucket_tags_request.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) 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 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"
|
||||
)
|
||||
|
||||
// PutBucketTagsRequest put bucket tags request
|
||||
//
|
||||
// swagger:model putBucketTagsRequest
|
||||
type PutBucketTagsRequest struct {
|
||||
|
||||
// tags
|
||||
Tags map[string]string `json:"tags,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this put bucket tags request
|
||||
func (m *PutBucketTagsRequest) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validates this put bucket tags request based on context it is used
|
||||
func (m *PutBucketTagsRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *PutBucketTagsRequest) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *PutBucketTagsRequest) UnmarshalBinary(b []byte) error {
|
||||
var res PutBucketTagsRequest
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
@@ -46,11 +46,8 @@ type SessionResponse struct {
|
||||
// operator
|
||||
Operator bool `json:"operator,omitempty"`
|
||||
|
||||
// pages
|
||||
Pages []string `json:"pages"`
|
||||
|
||||
// policy
|
||||
Policy *IamPolicy `json:"policy,omitempty"`
|
||||
// permissions
|
||||
Permissions map[string][]string `json:"permissions,omitempty"`
|
||||
|
||||
// status
|
||||
// Enum: [ok]
|
||||
@@ -61,10 +58,6 @@ type SessionResponse struct {
|
||||
func (m *SessionResponse) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validatePolicy(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateStatus(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
@@ -75,23 +68,6 @@ func (m *SessionResponse) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SessionResponse) validatePolicy(formats strfmt.Registry) error {
|
||||
if swag.IsZero(m.Policy) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.Policy != nil {
|
||||
if err := m.Policy.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("policy")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var sessionResponseTypeStatusPropEnum []interface{}
|
||||
|
||||
func init() {
|
||||
@@ -131,31 +107,8 @@ func (m *SessionResponse) validateStatus(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContextValidate validate this session response based on the context it is used
|
||||
// ContextValidate validates this session response based on context it is used
|
||||
func (m *SessionResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.contextValidatePolicy(ctx, formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SessionResponse) contextValidatePolicy(ctx context.Context, formats strfmt.Registry) error {
|
||||
|
||||
if m.Policy != nil {
|
||||
if err := m.Policy.ContextValidate(ctx, formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("policy")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,39 @@ func init() {
|
||||
},
|
||||
"basePath": "/api/v1",
|
||||
"paths": {
|
||||
"/cluster/allocatable-resources": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"OperatorAPI"
|
||||
],
|
||||
"summary": "Get allocatable cpu and memory for given number of nodes",
|
||||
"operationId": "GetAllocatableResources",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "num_nodes",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/allocatableResourcesResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cluster/max-allocatable-memory": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -272,38 +305,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Console",
|
||||
"operationId": "Login",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/oauth2/auth": {
|
||||
@@ -325,11 +326,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -359,11 +357,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -1420,6 +1415,25 @@ func init() {
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"allocatableResourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"mem_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"min_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"min_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"awsConfiguration": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -2215,14 +2229,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"maxAllocatableMemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -2275,6 +2281,19 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeMaxAllocatableResources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"max_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
@@ -2342,19 +2361,16 @@ func init() {
|
||||
"operatorSessionResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"pages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"permissions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
@@ -3236,6 +3252,39 @@ func init() {
|
||||
},
|
||||
"basePath": "/api/v1",
|
||||
"paths": {
|
||||
"/cluster/allocatable-resources": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"OperatorAPI"
|
||||
],
|
||||
"summary": "Get allocatable cpu and memory for given number of nodes",
|
||||
"operationId": "GetAllocatableResources",
|
||||
"parameters": [
|
||||
{
|
||||
"minimum": 1,
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "num_nodes",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/allocatableResourcesResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/cluster/max-allocatable-memory": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3456,38 +3505,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [],
|
||||
"tags": [
|
||||
"UserAPI"
|
||||
],
|
||||
"summary": "Login to Console",
|
||||
"operationId": "Login",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/login/oauth2/auth": {
|
||||
@@ -3509,11 +3526,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -3543,11 +3557,8 @@ func init() {
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "A successful login.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/loginResponse"
|
||||
}
|
||||
"204": {
|
||||
"description": "A successful login."
|
||||
},
|
||||
"default": {
|
||||
"description": "Generic error response.",
|
||||
@@ -5329,6 +5340,25 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"allocatableResourcesResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"mem_priority": {
|
||||
"$ref": "#/definitions/nodeMaxAllocatableResources"
|
||||
},
|
||||
"min_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"min_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"awsConfiguration": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@@ -6112,14 +6142,6 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"loginResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sessionId": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"maxAllocatableMemResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -6172,6 +6194,19 @@ func init() {
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeMaxAllocatableResources": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"max_allocatable_cpu": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"max_allocatable_mem": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nodeSelectorTerm": {
|
||||
"description": "A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm.",
|
||||
"type": "object",
|
||||
@@ -6195,19 +6230,16 @@ func init() {
|
||||
"operatorSessionResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"features": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"operator": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"pages": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"permissions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
|
||||
@@ -78,6 +78,9 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
|
||||
OperatorAPIDirectCSIFormatDriveHandler: operator_api.DirectCSIFormatDriveHandlerFunc(func(params operator_api.DirectCSIFormatDriveParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.DirectCSIFormatDrive has not yet been implemented")
|
||||
}),
|
||||
OperatorAPIGetAllocatableResourcesHandler: operator_api.GetAllocatableResourcesHandlerFunc(func(params operator_api.GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.GetAllocatableResources has not yet been implemented")
|
||||
}),
|
||||
OperatorAPIGetDirectCSIDriveListHandler: operator_api.GetDirectCSIDriveListHandlerFunc(func(params operator_api.GetDirectCSIDriveListParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.GetDirectCSIDriveList has not yet been implemented")
|
||||
}),
|
||||
@@ -123,9 +126,6 @@ func NewOperatorAPI(spec *loads.Document) *OperatorAPI {
|
||||
OperatorAPIListTenantsHandler: operator_api.ListTenantsHandlerFunc(func(params operator_api.ListTenantsParams, principal *models.Principal) middleware.Responder {
|
||||
return middleware.NotImplemented("operation operator_api.ListTenants has not yet been implemented")
|
||||
}),
|
||||
UserAPILoginHandler: user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.Login has not yet been implemented")
|
||||
}),
|
||||
UserAPILoginDetailHandler: user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation user_api.LoginDetail has not yet been implemented")
|
||||
}),
|
||||
@@ -239,6 +239,8 @@ type OperatorAPI struct {
|
||||
OperatorAPIDeleteTenantHandler operator_api.DeleteTenantHandler
|
||||
// OperatorAPIDirectCSIFormatDriveHandler sets the operation handler for the direct c s i format drive operation
|
||||
OperatorAPIDirectCSIFormatDriveHandler operator_api.DirectCSIFormatDriveHandler
|
||||
// OperatorAPIGetAllocatableResourcesHandler sets the operation handler for the get allocatable resources operation
|
||||
OperatorAPIGetAllocatableResourcesHandler operator_api.GetAllocatableResourcesHandler
|
||||
// OperatorAPIGetDirectCSIDriveListHandler sets the operation handler for the get direct c s i drive list operation
|
||||
OperatorAPIGetDirectCSIDriveListHandler operator_api.GetDirectCSIDriveListHandler
|
||||
// OperatorAPIGetDirectCSIVolumeListHandler sets the operation handler for the get direct c s i volume list operation
|
||||
@@ -269,8 +271,6 @@ type OperatorAPI struct {
|
||||
OperatorAPIListPVCsForTenantHandler operator_api.ListPVCsForTenantHandler
|
||||
// OperatorAPIListTenantsHandler sets the operation handler for the list tenants operation
|
||||
OperatorAPIListTenantsHandler operator_api.ListTenantsHandler
|
||||
// UserAPILoginHandler sets the operation handler for the login operation
|
||||
UserAPILoginHandler user_api.LoginHandler
|
||||
// UserAPILoginDetailHandler sets the operation handler for the login detail operation
|
||||
UserAPILoginDetailHandler user_api.LoginDetailHandler
|
||||
// UserAPILoginOauth2AuthHandler sets the operation handler for the login oauth2 auth operation
|
||||
@@ -403,6 +403,9 @@ func (o *OperatorAPI) Validate() error {
|
||||
if o.OperatorAPIDirectCSIFormatDriveHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.DirectCSIFormatDriveHandler")
|
||||
}
|
||||
if o.OperatorAPIGetAllocatableResourcesHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.GetAllocatableResourcesHandler")
|
||||
}
|
||||
if o.OperatorAPIGetDirectCSIDriveListHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.GetDirectCSIDriveListHandler")
|
||||
}
|
||||
@@ -448,9 +451,6 @@ func (o *OperatorAPI) Validate() error {
|
||||
if o.OperatorAPIListTenantsHandler == nil {
|
||||
unregistered = append(unregistered, "operator_api.ListTenantsHandler")
|
||||
}
|
||||
if o.UserAPILoginHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginHandler")
|
||||
}
|
||||
if o.UserAPILoginDetailHandler == nil {
|
||||
unregistered = append(unregistered, "user_api.LoginDetailHandler")
|
||||
}
|
||||
@@ -626,6 +626,10 @@ func (o *OperatorAPI) initHandlerCache() {
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/cluster/allocatable-resources"] = operator_api.NewGetAllocatableResources(o.context, o.OperatorAPIGetAllocatableResourcesHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/direct-csi/drives"] = operator_api.NewGetDirectCSIDriveList(o.context, o.OperatorAPIGetDirectCSIDriveListHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
@@ -683,10 +687,6 @@ func (o *OperatorAPI) initHandlerCache() {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["GET"]["/namespaces/{namespace}/tenants"] = operator_api.NewListTenants(o.context, o.OperatorAPIListTenantsHandler)
|
||||
if o.handlers["POST"] == nil {
|
||||
o.handlers["POST"] = make(map[string]http.Handler)
|
||||
}
|
||||
o.handlers["POST"]["/login"] = user_api.NewLogin(o.context, o.UserAPILoginHandler)
|
||||
if o.handlers["GET"] == nil {
|
||||
o.handlers["GET"] = make(map[string]http.Handler)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesHandlerFunc turns a function with the right signature into a get allocatable resources handler
|
||||
type GetAllocatableResourcesHandlerFunc func(GetAllocatableResourcesParams, *models.Principal) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn GetAllocatableResourcesHandlerFunc) Handle(params GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
return fn(params, principal)
|
||||
}
|
||||
|
||||
// GetAllocatableResourcesHandler interface for that can handle valid get allocatable resources params
|
||||
type GetAllocatableResourcesHandler interface {
|
||||
Handle(GetAllocatableResourcesParams, *models.Principal) middleware.Responder
|
||||
}
|
||||
|
||||
// NewGetAllocatableResources creates a new http.Handler for the get allocatable resources operation
|
||||
func NewGetAllocatableResources(ctx *middleware.Context, handler GetAllocatableResourcesHandler) *GetAllocatableResources {
|
||||
return &GetAllocatableResources{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/* GetAllocatableResources swagger:route GET /cluster/allocatable-resources OperatorAPI getAllocatableResources
|
||||
|
||||
Get allocatable cpu and memory for given number of nodes
|
||||
|
||||
*/
|
||||
type GetAllocatableResources struct {
|
||||
Context *middleware.Context
|
||||
Handler GetAllocatableResourcesHandler
|
||||
}
|
||||
|
||||
func (o *GetAllocatableResources) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
*r = *rCtx
|
||||
}
|
||||
var Params = NewGetAllocatableResourcesParams()
|
||||
uprinc, aCtx, err := o.Context.Authorize(r, route)
|
||||
if err != nil {
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
if aCtx != nil {
|
||||
*r = *aCtx
|
||||
}
|
||||
var principal *models.Principal
|
||||
if uprinc != nil {
|
||||
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
|
||||
}
|
||||
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params, principal) // actually handle the request
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// NewGetAllocatableResourcesParams creates a new GetAllocatableResourcesParams object
|
||||
//
|
||||
// There are no default values defined in the spec.
|
||||
func NewGetAllocatableResourcesParams() GetAllocatableResourcesParams {
|
||||
|
||||
return GetAllocatableResourcesParams{}
|
||||
}
|
||||
|
||||
// GetAllocatableResourcesParams contains all the bound params for the get allocatable resources operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters GetAllocatableResources
|
||||
type GetAllocatableResourcesParams struct {
|
||||
|
||||
// HTTP Request Object
|
||||
HTTPRequest *http.Request `json:"-"`
|
||||
|
||||
/*
|
||||
Required: true
|
||||
Minimum: 1
|
||||
In: query
|
||||
*/
|
||||
NumNodes int32
|
||||
}
|
||||
|
||||
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
|
||||
// for simple values it will use straight method calls.
|
||||
//
|
||||
// To ensure default values, the struct must have been initialized with NewGetAllocatableResourcesParams() beforehand.
|
||||
func (o *GetAllocatableResourcesParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
qs := runtime.Values(r.URL.Query())
|
||||
|
||||
qNumNodes, qhkNumNodes, _ := qs.GetOK("num_nodes")
|
||||
if err := o.bindNumNodes(qNumNodes, qhkNumNodes, route.Formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindNumNodes binds and validates parameter NumNodes from query.
|
||||
func (o *GetAllocatableResourcesParams) bindNumNodes(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||
if !hasKey {
|
||||
return errors.Required("num_nodes", "query", rawData)
|
||||
}
|
||||
var raw string
|
||||
if len(rawData) > 0 {
|
||||
raw = rawData[len(rawData)-1]
|
||||
}
|
||||
|
||||
// Required: true
|
||||
// AllowEmptyValue: false
|
||||
|
||||
if err := validate.RequiredString("num_nodes", "query", raw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value, err := swag.ConvertInt32(raw)
|
||||
if err != nil {
|
||||
return errors.InvalidType("num_nodes", "query", "int32", raw)
|
||||
}
|
||||
o.NumNodes = value
|
||||
|
||||
if err := o.validateNumNodes(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateNumNodes carries on validations for parameter NumNodes
|
||||
func (o *GetAllocatableResourcesParams) validateNumNodes(formats strfmt.Registry) error {
|
||||
|
||||
if err := validate.MinimumInt("num_nodes", "query", int64(o.NumNodes), 1, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesOKCode is the HTTP code returned for type GetAllocatableResourcesOK
|
||||
const GetAllocatableResourcesOKCode int = 200
|
||||
|
||||
/*GetAllocatableResourcesOK A successful response.
|
||||
|
||||
swagger:response getAllocatableResourcesOK
|
||||
*/
|
||||
type GetAllocatableResourcesOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.AllocatableResourcesResponse `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetAllocatableResourcesOK creates GetAllocatableResourcesOK with default headers values
|
||||
func NewGetAllocatableResourcesOK() *GetAllocatableResourcesOK {
|
||||
|
||||
return &GetAllocatableResourcesOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get allocatable resources o k response
|
||||
func (o *GetAllocatableResourcesOK) WithPayload(payload *models.AllocatableResourcesResponse) *GetAllocatableResourcesOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get allocatable resources o k response
|
||||
func (o *GetAllocatableResourcesOK) SetPayload(payload *models.AllocatableResourcesResponse) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetAllocatableResourcesOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(200)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*GetAllocatableResourcesDefault Generic error response.
|
||||
|
||||
swagger:response getAllocatableResourcesDefault
|
||||
*/
|
||||
type GetAllocatableResourcesDefault struct {
|
||||
_statusCode int
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.Error `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewGetAllocatableResourcesDefault creates GetAllocatableResourcesDefault with default headers values
|
||||
func NewGetAllocatableResourcesDefault(code int) *GetAllocatableResourcesDefault {
|
||||
if code <= 0 {
|
||||
code = 500
|
||||
}
|
||||
|
||||
return &GetAllocatableResourcesDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatusCode adds the status to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) WithStatusCode(code int) *GetAllocatableResourcesDefault {
|
||||
o._statusCode = code
|
||||
return o
|
||||
}
|
||||
|
||||
// SetStatusCode sets the status to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) SetStatusCode(code int) {
|
||||
o._statusCode = code
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) WithPayload(payload *models.Error) *GetAllocatableResourcesDefault {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the get allocatable resources default response
|
||||
func (o *GetAllocatableResourcesDefault) SetPayload(payload *models.Error) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *GetAllocatableResourcesDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(o._statusCode)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 operator_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
golangswaggerpaths "path"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// GetAllocatableResourcesURL generates an URL for the get allocatable resources operation
|
||||
type GetAllocatableResourcesURL struct {
|
||||
NumNodes int32
|
||||
|
||||
_basePath string
|
||||
// avoid unkeyed usage
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// WithBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetAllocatableResourcesURL) WithBasePath(bp string) *GetAllocatableResourcesURL {
|
||||
o.SetBasePath(bp)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBasePath sets the base path for this url builder, only required when it's different from the
|
||||
// base path specified in the swagger spec.
|
||||
// When the value of the base path is an empty string
|
||||
func (o *GetAllocatableResourcesURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *GetAllocatableResourcesURL) Build() (*url.URL, error) {
|
||||
var _result url.URL
|
||||
|
||||
var _path = "/cluster/allocatable-resources"
|
||||
|
||||
_basePath := o._basePath
|
||||
if _basePath == "" {
|
||||
_basePath = "/api/v1"
|
||||
}
|
||||
_result.Path = golangswaggerpaths.Join(_basePath, _path)
|
||||
|
||||
qs := make(url.Values)
|
||||
|
||||
numNodesQ := swag.FormatInt32(o.NumNodes)
|
||||
if numNodesQ != "" {
|
||||
qs.Set("num_nodes", numNodesQ)
|
||||
}
|
||||
|
||||
_result.RawQuery = qs.Encode()
|
||||
|
||||
return &_result, nil
|
||||
}
|
||||
|
||||
// Must is a helper function to panic when the url builder returns an error
|
||||
func (o *GetAllocatableResourcesURL) Must(u *url.URL, err error) *url.URL {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if u == nil {
|
||||
panic("url can't be nil")
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
// String returns the string representation of the path with query string
|
||||
func (o *GetAllocatableResourcesURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *GetAllocatableResourcesURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on GetAllocatableResourcesURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on GetAllocatableResourcesURL")
|
||||
}
|
||||
|
||||
base, err := o.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.Scheme = scheme
|
||||
base.Host = host
|
||||
return base, nil
|
||||
}
|
||||
|
||||
// StringFull returns the string representation of a complete url
|
||||
func (o *GetAllocatableResourcesURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
// 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 user_api
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the generate command
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// LoginHandlerFunc turns a function with the right signature into a login handler
|
||||
type LoginHandlerFunc func(LoginParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn LoginHandlerFunc) Handle(params LoginParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// LoginHandler interface for that can handle valid login params
|
||||
type LoginHandler interface {
|
||||
Handle(LoginParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewLogin creates a new http.Handler for the login operation
|
||||
func NewLogin(ctx *middleware.Context, handler LoginHandler) *Login {
|
||||
return &Login{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/* Login swagger:route POST /login UserAPI login
|
||||
|
||||
Login to Console
|
||||
|
||||
*/
|
||||
type Login struct {
|
||||
Context *middleware.Context
|
||||
Handler LoginHandler
|
||||
}
|
||||
|
||||
func (o *Login) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
*r = *rCtx
|
||||
}
|
||||
var Params = NewLoginParams()
|
||||
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
|
||||
o.Context.Respond(rw, r, route.Produces, route, err)
|
||||
return
|
||||
}
|
||||
|
||||
res := o.Handler.Handle(Params) // actually handle the request
|
||||
o.Context.Respond(rw, r, route.Produces, route, res)
|
||||
|
||||
}
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOauth2AuthCreatedCode is the HTTP code returned for type LoginOauth2AuthCreated
|
||||
const LoginOauth2AuthCreatedCode int = 201
|
||||
// LoginOauth2AuthNoContentCode is the HTTP code returned for type LoginOauth2AuthNoContent
|
||||
const LoginOauth2AuthNoContentCode int = 204
|
||||
|
||||
/*LoginOauth2AuthCreated A successful login.
|
||||
/*LoginOauth2AuthNoContent A successful login.
|
||||
|
||||
swagger:response loginOauth2AuthCreated
|
||||
swagger:response loginOauth2AuthNoContent
|
||||
*/
|
||||
type LoginOauth2AuthCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginOauth2AuthNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginOauth2AuthCreated creates LoginOauth2AuthCreated with default headers values
|
||||
func NewLoginOauth2AuthCreated() *LoginOauth2AuthCreated {
|
||||
// NewLoginOauth2AuthNoContent creates LoginOauth2AuthNoContent with default headers values
|
||||
func NewLoginOauth2AuthNoContent() *LoginOauth2AuthNoContent {
|
||||
|
||||
return &LoginOauth2AuthCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) WithPayload(payload *models.LoginResponse) *LoginOauth2AuthCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login oauth2 auth created response
|
||||
func (o *LoginOauth2AuthCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginOauth2AuthNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOauth2AuthCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginOauth2AuthNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginOauth2AuthDefault Generic error response.
|
||||
|
||||
@@ -30,48 +30,28 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
)
|
||||
|
||||
// LoginOperatorCreatedCode is the HTTP code returned for type LoginOperatorCreated
|
||||
const LoginOperatorCreatedCode int = 201
|
||||
// LoginOperatorNoContentCode is the HTTP code returned for type LoginOperatorNoContent
|
||||
const LoginOperatorNoContentCode int = 204
|
||||
|
||||
/*LoginOperatorCreated A successful login.
|
||||
/*LoginOperatorNoContent A successful login.
|
||||
|
||||
swagger:response loginOperatorCreated
|
||||
swagger:response loginOperatorNoContent
|
||||
*/
|
||||
type LoginOperatorCreated struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.LoginResponse `json:"body,omitempty"`
|
||||
type LoginOperatorNoContent struct {
|
||||
}
|
||||
|
||||
// NewLoginOperatorCreated creates LoginOperatorCreated with default headers values
|
||||
func NewLoginOperatorCreated() *LoginOperatorCreated {
|
||||
// NewLoginOperatorNoContent creates LoginOperatorNoContent with default headers values
|
||||
func NewLoginOperatorNoContent() *LoginOperatorNoContent {
|
||||
|
||||
return &LoginOperatorCreated{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) WithPayload(payload *models.LoginResponse) *LoginOperatorCreated {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the login operator created response
|
||||
func (o *LoginOperatorCreated) SetPayload(payload *models.LoginResponse) {
|
||||
o.Payload = payload
|
||||
return &LoginOperatorNoContent{}
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *LoginOperatorCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
func (o *LoginOperatorNoContent) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
|
||||
|
||||
rw.WriteHeader(201)
|
||||
if o.Payload != nil {
|
||||
payload := o.Payload
|
||||
if err := producer.Produce(rw, payload); err != nil {
|
||||
panic(err) // let the recovery middleware deal with this
|
||||
}
|
||||
}
|
||||
rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses
|
||||
|
||||
rw.WriteHeader(204)
|
||||
}
|
||||
|
||||
/*LoginOperatorDefault Generic error response.
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
xoauth2 "golang.org/x/oauth2"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
|
||||
@@ -33,39 +37,15 @@ import (
|
||||
)
|
||||
|
||||
func registerLoginHandlers(api *operations.OperatorAPI) {
|
||||
// get login strategy
|
||||
// GET login strategy
|
||||
api.UserAPILoginDetailHandler = user_api.LoginDetailHandlerFunc(func(params user_api.LoginDetailParams) middleware.Responder {
|
||||
loginDetails, err := getLoginDetailsResponse()
|
||||
loginDetails, err := getLoginDetailsResponse(params.HTTPRequest)
|
||||
if err != nil {
|
||||
return user_api.NewLoginDetailDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return user_api.NewLoginDetailOK().WithPayload(loginDetails)
|
||||
})
|
||||
// post login
|
||||
api.UserAPILoginHandler = user_api.LoginHandlerFunc(func(params user_api.LoginParams) middleware.Responder {
|
||||
loginResponse, err := getLoginResponse(params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse()
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// POST login using k8s service account token
|
||||
api.UserAPILoginOperatorHandler = user_api.LoginOperatorHandlerFunc(func(params user_api.LoginOperatorParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOperatorResponse(params.Body)
|
||||
if err != nil {
|
||||
@@ -75,7 +55,20 @@ func registerLoginHandlers(api *operations.OperatorAPI) {
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOperatorCreated().WithPayload(loginResponse).WriteResponse(w, p)
|
||||
user_api.NewLoginOperatorNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
// POST login using external IDP
|
||||
api.UserAPILoginOauth2AuthHandler = user_api.LoginOauth2AuthHandlerFunc(func(params user_api.LoginOauth2AuthParams) middleware.Responder {
|
||||
loginResponse, err := getLoginOauth2AuthResponse(params.HTTPRequest, params.Body)
|
||||
if err != nil {
|
||||
return user_api.NewLoginOauth2AuthDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
// Custom response writer to set the session cookies
|
||||
return middleware.ResponderFunc(func(w http.ResponseWriter, p runtime.Producer) {
|
||||
cookie := restapi.NewSessionCookieForConsole(loginResponse.SessionID)
|
||||
http.SetCookie(w, &cookie)
|
||||
user_api.NewLoginOauth2AuthNoContent().WriteResponse(w, p)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -97,45 +90,15 @@ func login(credentials restapi.ConsoleCredentialsI) (*string, error) {
|
||||
return &token, nil
|
||||
}
|
||||
|
||||
// getConsoleCredentials will return consoleCredentials interface including the associated policy of the current account
|
||||
func getConsoleCredentials(accessKey, secretKey string) (*restapi.ConsoleCredentials, error) {
|
||||
creds, err := newConsoleCredentials(secretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &restapi.ConsoleCredentials{
|
||||
ConsoleCredentials: creds,
|
||||
AccountAccessKey: accessKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// getLoginResponse performs login() and serializes it to the handler's output
|
||||
func getLoginResponse(lr *models.LoginRequest) (*models.LoginResponse, *models.Error) {
|
||||
// prepare console credentials
|
||||
consolCreds, err := getConsoleCredentials(*lr.AccessKey, *lr.SecretKey)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
sessionID, err := login(consolCreds)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *sessionID,
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
|
||||
// getLoginDetailsResponse returns information regarding the Console authentication mechanism.
|
||||
func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) {
|
||||
func getLoginDetailsResponse(r *http.Request) (*models.LoginDetails, *models.Error) {
|
||||
loginStrategy := models.LoginDetailsLoginStrategyServiceDashAccount
|
||||
redirectURL := ""
|
||||
|
||||
if oauth2.IsIDPEnabled() {
|
||||
loginStrategy = models.LoginDetailsLoginStrategyRedirect
|
||||
// initialize new oauth2 client
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, restapi.GetConsoleHTTPClient())
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
@@ -151,22 +114,48 @@ func getLoginDetailsResponse() (*models.LoginDetails, *models.Error) {
|
||||
return loginDetails, nil
|
||||
}
|
||||
|
||||
func getLoginOauth2AuthResponse() (*models.LoginResponse, *models.Error) {
|
||||
// verifyUserAgainstIDP will verify user identity against the configured IDP and return MinIO credentials
|
||||
func verifyUserAgainstIDP(ctx context.Context, provider auth.IdentityProviderI, code, state string) (*xoauth2.Token, error) {
|
||||
oauth2Token, err := provider.VerifyIdentityForOperator(ctx, code, state)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauth2Token, nil
|
||||
}
|
||||
|
||||
creds, err := newConsoleCredentials(getK8sSAToken())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
func getLoginOauth2AuthResponse(r *http.Request, lr *models.LoginOauth2AuthRequest) (*models.LoginResponse, *models.Error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
defer cancel()
|
||||
if oauth2.IsIDPEnabled() {
|
||||
// initialize new oauth2 client
|
||||
oauth2Client, err := oauth2.NewOauth2ProviderClient(nil, r, restapi.GetConsoleHTTPClient())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// initialize new identity provider
|
||||
identityProvider := auth.IdentityProvider{Client: oauth2Client}
|
||||
// Validate user against IDP
|
||||
_, err = verifyUserAgainstIDP(ctx, identityProvider, *lr.Code, *lr.State)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
// If we pass here that means the IDP correctly authenticate the user with the operator resource
|
||||
// we proceed to use the service account token configured in the operator-console pod
|
||||
creds, err := newConsoleCredentials(getK8sSAToken())
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
token, err := login(restapi.ConsoleCredentials{ConsoleCredentials: creds})
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *token,
|
||||
}
|
||||
return loginResponse, nil
|
||||
}
|
||||
consoleCredentials := restapi.ConsoleCredentials{ConsoleCredentials: creds}
|
||||
token, err := login(consoleCredentials)
|
||||
if err != nil {
|
||||
return nil, prepareError(errInvalidCredentials, nil, err)
|
||||
}
|
||||
// serialize output
|
||||
loginResponse := &models.LoginResponse{
|
||||
SessionID: *token,
|
||||
}
|
||||
return loginResponse, nil
|
||||
return nil, prepareError(errorGeneric)
|
||||
}
|
||||
|
||||
func newConsoleCredentials(secretKey string) (*credentials.Credentials, error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package operatorapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/set"
|
||||
@@ -50,6 +51,20 @@ func registerNodesHandlers(api *operations.OperatorAPI) {
|
||||
}
|
||||
return operator_api.NewListNodeLabelsOK().WithPayload(*resp)
|
||||
})
|
||||
|
||||
api.OperatorAPIGetAllocatableResourcesHandler = operator_api.GetAllocatableResourcesHandlerFunc(func(params operator_api.GetAllocatableResourcesParams, principal *models.Principal) middleware.Responder {
|
||||
resp, err := getAllocatableResourcesResponse(params.NumNodes, principal)
|
||||
if err != nil {
|
||||
return operator_api.NewGetAllocatableResourcesDefault(int(err.Code)).WithPayload(err)
|
||||
}
|
||||
return operator_api.NewGetAllocatableResourcesOK().WithPayload(resp)
|
||||
})
|
||||
}
|
||||
|
||||
type NodeResourceInfo struct {
|
||||
Name string
|
||||
AllocatableMemory int64
|
||||
AllocatableCPU int64
|
||||
}
|
||||
|
||||
// getMaxAllocatableMemory get max allocatable memory given a desired number of nodes
|
||||
@@ -211,3 +226,147 @@ func getNodeLabelsResponse(ctx context.Context, session *models.Principal) (*mod
|
||||
}
|
||||
return clusterResources, nil
|
||||
}
|
||||
|
||||
func getClusterResourcesInfo(numNodes int32, inNodesResources []NodeResourceInfo) *models.AllocatableResourcesResponse {
|
||||
|
||||
// purge any nodes with 0 cpu
|
||||
var nodesResources []NodeResourceInfo
|
||||
for _, n := range inNodesResources {
|
||||
if n.AllocatableCPU > 0 {
|
||||
nodesResources = append(nodesResources, n)
|
||||
}
|
||||
}
|
||||
|
||||
if int32(len(nodesResources)) < numNodes || numNodes == 0 {
|
||||
return &models.AllocatableResourcesResponse{
|
||||
CPUPriority: &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: 0,
|
||||
MaxAllocatableMem: 0,
|
||||
},
|
||||
MemPriority: &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: 0,
|
||||
MaxAllocatableMem: 0,
|
||||
},
|
||||
MinAllocatableCPU: 0,
|
||||
MinAllocatableMem: 0,
|
||||
}
|
||||
}
|
||||
|
||||
allocatableResources := &models.AllocatableResourcesResponse{}
|
||||
|
||||
// sort nodesResources giving CPU priority
|
||||
sort.Slice(nodesResources, func(i, j int) bool { return nodesResources[i].AllocatableCPU < nodesResources[j].AllocatableCPU })
|
||||
maxCPUNodesNeeded := len(nodesResources) - int(numNodes)
|
||||
maxMemNodesNeeded := maxCPUNodesNeeded
|
||||
|
||||
maxAllocatableCPU := nodesResources[maxCPUNodesNeeded].AllocatableCPU
|
||||
minAllocatableCPU := nodesResources[maxCPUNodesNeeded].AllocatableCPU
|
||||
minAllocatableMem := nodesResources[maxMemNodesNeeded].AllocatableMemory
|
||||
|
||||
availableMemsForMaxCPU := []int64{}
|
||||
for _, info := range nodesResources {
|
||||
if info.AllocatableCPU >= maxAllocatableCPU {
|
||||
availableMemsForMaxCPU = append(availableMemsForMaxCPU, info.AllocatableMemory)
|
||||
}
|
||||
// min allocatable resources overall
|
||||
minAllocatableCPU = min(minAllocatableCPU, info.AllocatableCPU)
|
||||
minAllocatableMem = min(minAllocatableMem, info.AllocatableMemory)
|
||||
}
|
||||
|
||||
sort.Slice(availableMemsForMaxCPU, func(i, j int) bool { return availableMemsForMaxCPU[i] < availableMemsForMaxCPU[j] })
|
||||
maxAllocatableMem := availableMemsForMaxCPU[len(availableMemsForMaxCPU)-int(numNodes)]
|
||||
|
||||
allocatableResources.MinAllocatableCPU = minAllocatableCPU
|
||||
allocatableResources.MinAllocatableMem = minAllocatableMem
|
||||
allocatableResources.CPUPriority = &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: maxAllocatableCPU,
|
||||
MaxAllocatableMem: maxAllocatableMem,
|
||||
}
|
||||
|
||||
// sort nodesResources giving Mem priority
|
||||
sort.Slice(nodesResources, func(i, j int) bool { return nodesResources[i].AllocatableMemory < nodesResources[j].AllocatableMemory })
|
||||
maxMemNodesNeeded = len(nodesResources) - int(numNodes)
|
||||
maxAllocatableMem = nodesResources[maxMemNodesNeeded].AllocatableMemory
|
||||
|
||||
availableCPUsForMaxMem := []int64{}
|
||||
for _, info := range nodesResources {
|
||||
if info.AllocatableMemory >= maxAllocatableMem {
|
||||
availableCPUsForMaxMem = append(availableCPUsForMaxMem, info.AllocatableCPU)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(availableCPUsForMaxMem, func(i, j int) bool { return availableCPUsForMaxMem[i] < availableCPUsForMaxMem[j] })
|
||||
maxAllocatableCPU = availableCPUsForMaxMem[len(availableCPUsForMaxMem)-int(numNodes)]
|
||||
|
||||
allocatableResources.MemPriority = &models.NodeMaxAllocatableResources{
|
||||
MaxAllocatableCPU: maxAllocatableCPU,
|
||||
MaxAllocatableMem: maxAllocatableMem,
|
||||
}
|
||||
|
||||
return allocatableResources
|
||||
}
|
||||
|
||||
// getAllocatableResources get max allocatable memory given a desired number of nodes
|
||||
func getAllocatableResources(ctx context.Context, clientset v1.CoreV1Interface, numNodes int32) (*models.AllocatableResourcesResponse, error) {
|
||||
if numNodes == 0 {
|
||||
return nil, errors.New("error NumNodes must be greated than 0")
|
||||
}
|
||||
|
||||
// get all nodes from cluster
|
||||
nodes, err := clientset.Nodes().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nodesInfo := []NodeResourceInfo{}
|
||||
OUTER:
|
||||
for _, n := range nodes.Items {
|
||||
// Don't consider node if it has a NoSchedule or NoExecute Taint
|
||||
for _, t := range n.Spec.Taints {
|
||||
switch t.Effect {
|
||||
case corev1.TaintEffectNoSchedule:
|
||||
continue OUTER
|
||||
case corev1.TaintEffectNoExecute:
|
||||
continue OUTER
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
var nodeMemory int64
|
||||
var nodeCPU int64
|
||||
if quantity, ok := n.Status.Allocatable[corev1.ResourceMemory]; ok {
|
||||
// availableMemSizes = append(availableMemSizes, quantity.Value())
|
||||
nodeMemory = quantity.Value()
|
||||
}
|
||||
// we assume all nodes have allocatable cpu resource
|
||||
if quantity, ok := n.Status.Allocatable[corev1.ResourceCPU]; ok {
|
||||
// availableCPU = append(availableCPU, quantity.Value())
|
||||
nodeCPU = quantity.Value()
|
||||
}
|
||||
nodeInfo := NodeResourceInfo{
|
||||
Name: n.Name,
|
||||
AllocatableCPU: nodeCPU,
|
||||
AllocatableMemory: nodeMemory,
|
||||
}
|
||||
nodesInfo = append(nodesInfo, nodeInfo)
|
||||
}
|
||||
res := getClusterResourcesInfo(numNodes, nodesInfo)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Get allocatable resources response
|
||||
|
||||
func getAllocatableResourcesResponse(numNodes int32, session *models.Principal) (*models.AllocatableResourcesResponse, *models.Error) {
|
||||
ctx := context.Background()
|
||||
client, err := cluster.K8sClient(session.STSSessionToken)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
clusterResources, err := getAllocatableResources(ctx, client.CoreV1(), numNodes)
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
return clusterResources, nil
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"github.com/minio/console/models"
|
||||
"github.com/minio/console/operatorapi/operations"
|
||||
"github.com/minio/console/operatorapi/operations/user_api"
|
||||
"github.com/minio/console/pkg/acl"
|
||||
)
|
||||
|
||||
func registerSessionHandlers(api *operations.OperatorAPI) {
|
||||
@@ -42,16 +41,9 @@ func getSessionResponse(session *models.Principal) (*models.OperatorSessionRespo
|
||||
return nil, prepareError(errorGenericInvalidSession)
|
||||
}
|
||||
sessionResp := &models.OperatorSessionResponse{
|
||||
Pages: acl.GetAuthorizedEndpoints([]string{}),
|
||||
Features: getListOfEnabledFeatures(),
|
||||
Status: models.OperatorSessionResponseStatusOk,
|
||||
Operator: true,
|
||||
Status: models.OperatorSessionResponseStatusOk,
|
||||
Operator: true,
|
||||
Permissions: map[string][]string{},
|
||||
}
|
||||
return sessionResp, nil
|
||||
}
|
||||
|
||||
// getListOfEnabledFeatures returns a list of features
|
||||
func getListOfEnabledFeatures() []string {
|
||||
var features []string
|
||||
return features
|
||||
}
|
||||
|
||||
@@ -943,6 +943,11 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
|
||||
},
|
||||
}
|
||||
|
||||
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// Enable/Disable console object browser for MinIO tenant (default is on)
|
||||
enabledConsole := "on"
|
||||
if tenantReq.EnableConsole != nil && !*tenantReq.EnableConsole {
|
||||
@@ -952,11 +957,6 @@ func getTenantCreatedResponse(session *models.Principal, params operator_api.Cre
|
||||
tenantConfigurationENV["MINIO_ROOT_USER"] = accessKey
|
||||
tenantConfigurationENV["MINIO_ROOT_PASSWORD"] = secretKey
|
||||
|
||||
_, err = clientSet.CoreV1().Secrets(ns).Create(ctx, &instanceSecret, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
|
||||
// delete secrets created if an error occurred during tenant creation,
|
||||
defer func() {
|
||||
if mError != nil {
|
||||
|
||||
@@ -19,6 +19,7 @@ package operatorapi
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
@@ -307,6 +308,10 @@ func createOrReplaceExternalCertSecrets(ctx context.Context, clientSet K8sClient
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// check if the key pair is valid
|
||||
if _, err = tls.X509KeyPair(tlsCrt, tlsKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
externalTLSCertificateSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: keyPairSecretName,
|
||||
|
||||
@@ -185,7 +185,8 @@ func serveProxy(responseWriter http.ResponseWriter, req *http.Request) {
|
||||
responseWriter.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
targetURL.Path = strings.Replace(req.URL.Path, fmt.Sprintf("/api/proxy/%s/%s", tenant.Namespace, tenant.Name), "", -1)
|
||||
tenantBase := fmt.Sprintf("/api/proxy/%s/%s", tenant.Namespace, tenant.Name)
|
||||
targetURL.Path = strings.Replace(req.URL.Path, tenantBase, "", -1)
|
||||
|
||||
proxiedCookie := &http.Cookie{
|
||||
Name: "token",
|
||||
@@ -207,8 +208,17 @@ func serveProxy(responseWriter http.ResponseWriter, req *http.Request) {
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}}
|
||||
|
||||
// are we proxying something with cp=y? (console proxy) then add cpb (console proxy base) so the console
|
||||
// on the other side updates the <base href="" /> to this value overriding sub path or root
|
||||
if v := req.URL.Query().Get("cp"); v == "y" {
|
||||
q := req.URL.Query()
|
||||
q.Add("cpb", tenantBase)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
// copy query params
|
||||
targetURL.RawQuery = req.URL.Query().Encode()
|
||||
|
||||
proxRequest, err := http.NewRequest(req.Method, targetURL.String(), req.Body)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
||||
@@ -1,455 +0,0 @@
|
||||
// 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 acl
|
||||
|
||||
import (
|
||||
iampolicy "github.com/minio/pkg/iam/policy"
|
||||
)
|
||||
|
||||
// endpoints definition
|
||||
var (
|
||||
configuration = "/settings"
|
||||
configurationItem = "/settings/:option"
|
||||
notificationEndpoints = "/notification-endpoints"
|
||||
notificationEndpointsAddAny = "/notification-endpoints/add/:service"
|
||||
notificationEndpointsAdd = "/notification-endpoints/add"
|
||||
tiers = "/tiers"
|
||||
tiersAddAny = "/tiers/add/:service"
|
||||
tiersAdd = "/tiers/add"
|
||||
users = "/users"
|
||||
usersDetail = "/users/:userName+"
|
||||
groups = "/groups"
|
||||
groupsDetails = "/groups/:groupName+"
|
||||
iamPolicies = "/policies"
|
||||
policiesDetail = "/policies/*"
|
||||
dashboard = "/dashboard"
|
||||
metrics = "/metrics"
|
||||
profiling = "/profiling"
|
||||
buckets = "/buckets"
|
||||
bucketsGeneral = "/buckets/*"
|
||||
bucketsAdmin = "/buckets/:bucketName/admin/*"
|
||||
bucketsAdminMain = "/buckets/:bucketName/admin"
|
||||
bucketsBrowserMenu = "/buckets"
|
||||
bucketsBrowserList = "/buckets/*"
|
||||
bucketsBrowser = "/buckets/:bucketName/browse/*"
|
||||
bucketsBrowserMain = "/buckets/:bucketName/browse"
|
||||
serviceAccounts = "/account"
|
||||
changePassword = "/account/change-password"
|
||||
tenants = "/tenants"
|
||||
tenantsAdd = "/tenants/add"
|
||||
tenantsAddSub = "/tenants/add/*"
|
||||
tenantsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName"
|
||||
tenantHop = "/namespaces/:tenantNamespace/tenants/:tenantName/hop"
|
||||
podsDetail = "/namespaces/:tenantNamespace/tenants/:tenantName/pods/:podName"
|
||||
tenantsDetailSummary = "/namespaces/:tenantNamespace/tenants/:tenantName/summary"
|
||||
tenantsDetailMetrics = "/namespaces/:tenantNamespace/tenants/:tenantName/metrics"
|
||||
tenantsDetailPods = "/namespaces/:tenantNamespace/tenants/:tenantName/pods"
|
||||
tenantsDetailPools = "/namespaces/:tenantNamespace/tenants/:tenantName/pools"
|
||||
tenantsDetailVolumes = "/namespaces/:tenantNamespace/tenants/:tenantName/volumes"
|
||||
tenantsDetailLicense = "/namespaces/:tenantNamespace/tenants/:tenantName/license"
|
||||
tenantsDetailSecurity = "/namespaces/:tenantNamespace/tenants/:tenantName/security"
|
||||
storage = "/storage"
|
||||
storageVolumes = "/storage/volumes"
|
||||
storageDrives = "/storage/drives"
|
||||
remoteBuckets = "/remote-buckets"
|
||||
replication = "/replication"
|
||||
license = "/license"
|
||||
watch = "/tools/watch"
|
||||
heal = "/tools/heal"
|
||||
trace = "/tools/trace"
|
||||
tools = "/tools"
|
||||
logs = "/tools/logs"
|
||||
auditLogs = "/tools/audit-logs"
|
||||
healthInfo = "/tools/diagnostics"
|
||||
)
|
||||
|
||||
type ConfigurationActionSet struct {
|
||||
actionTypes iampolicy.ActionSet
|
||||
actions iampolicy.ActionSet
|
||||
}
|
||||
|
||||
// configurationActionSet contains the list of admin actions required for this endpoint to work
|
||||
var configurationActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ConfigUpdateAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// dashboardActionSet contains the list of admin actions required for this endpoint to work
|
||||
var dashboardActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ServerInfoAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// groupsActionSet contains the list of admin actions required for this endpoint to work
|
||||
var groupsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ListGroupsAdminAction,
|
||||
iampolicy.AddUserToGroupAdminAction,
|
||||
//iampolicy.GetGroupAdminAction,
|
||||
iampolicy.EnableGroupAdminAction,
|
||||
iampolicy.DisableGroupAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// iamPoliciesActionSet contains the list of admin actions required for this endpoint to work
|
||||
var iamPoliciesActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.GetPolicyAdminAction,
|
||||
iampolicy.DeletePolicyAdminAction,
|
||||
iampolicy.CreatePolicyAdminAction,
|
||||
iampolicy.AttachPolicyAdminAction,
|
||||
iampolicy.ListUserPoliciesAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// profilingActionSet contains the list of admin actions required for this endpoint to work
|
||||
var profilingActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ProfilingAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// usersActionSet contains the list of admin actions required for this endpoint to work
|
||||
var usersActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ListUsersAdminAction,
|
||||
iampolicy.CreateUserAdminAction,
|
||||
iampolicy.DeleteUserAdminAction,
|
||||
iampolicy.GetUserAdminAction,
|
||||
iampolicy.EnableUserAdminAction,
|
||||
iampolicy.DisableUserAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// bucketsActionSet contains the list of admin actions required for this endpoint to work
|
||||
var bucketsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
// Read access to buckets
|
||||
iampolicy.ListMultipartUploadPartsAction,
|
||||
iampolicy.ListBucketMultipartUploadsAction,
|
||||
iampolicy.ListBucketAction,
|
||||
iampolicy.HeadBucketAction,
|
||||
iampolicy.GetObjectAction,
|
||||
iampolicy.GetBucketLocationAction,
|
||||
// Write access to buckets
|
||||
iampolicy.AbortMultipartUploadAction,
|
||||
iampolicy.CreateBucketAction,
|
||||
iampolicy.PutObjectAction,
|
||||
iampolicy.DeleteObjectAction,
|
||||
iampolicy.DeleteBucketAction,
|
||||
// Assign bucket policies
|
||||
iampolicy.PutBucketPolicyAction,
|
||||
iampolicy.DeleteBucketPolicyAction,
|
||||
iampolicy.GetBucketPolicyAction,
|
||||
),
|
||||
}
|
||||
|
||||
// serviceAccountsActionSet no actions needed for this module to work
|
||||
var serviceAccountsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
// changePasswordActionSet requires admin:CreateUser policy permission
|
||||
var changePasswordActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
// tenantsActionSet temporally no actions needed for tenants sections to work
|
||||
var tenantsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
var storageActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
var remoteBucketsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ConfigUpdateAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
var replicationActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ConfigUpdateAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// objectBrowserActionSet no actions needed for this module to work
|
||||
var objectBrowserActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
// licenseActionSet no actions needed for this module to work
|
||||
var licenseActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(),
|
||||
actions: iampolicy.NewActionSet(),
|
||||
}
|
||||
|
||||
// watchActionSet contains the list of admin actions required for this endpoint to work
|
||||
var watchActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ListenBucketNotificationAction,
|
||||
),
|
||||
}
|
||||
|
||||
// healActionSet contains the list of admin actions required for this endpoint to work
|
||||
var healActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.HealAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// logsActionSet contains the list of admin actions required for this endpoint to work
|
||||
var logsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ConsoleLogAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// toolsActionSet contains the list of admin actions required for this endpoint to work
|
||||
var toolsActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.ConsoleLogAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// traceActionSet contains the list of admin actions required for this endpoint to work
|
||||
var traceActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.TraceAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
// healthInfoActionSet contains the list of admin actions required for this endpoint to work
|
||||
var healthInfoActionSet = ConfigurationActionSet{
|
||||
actionTypes: iampolicy.NewActionSet(
|
||||
iampolicy.AllAdminActions,
|
||||
),
|
||||
actions: iampolicy.NewActionSet(
|
||||
iampolicy.HealthInfoAdminAction,
|
||||
),
|
||||
}
|
||||
|
||||
var displayRules = map[string]func() bool{
|
||||
// disable users page if LDAP is enabled
|
||||
users: func() bool {
|
||||
return !GetLDAPEnabled()
|
||||
},
|
||||
// disable groups page if LDAP is enabled
|
||||
groups: func() bool {
|
||||
return !GetLDAPEnabled()
|
||||
},
|
||||
}
|
||||
|
||||
// endpointRules contains the mapping between endpoints and ActionSets, additional rules can be added here
|
||||
var endpointRules = map[string]ConfigurationActionSet{
|
||||
configuration: configurationActionSet,
|
||||
configurationItem: configurationActionSet,
|
||||
notificationEndpoints: configurationActionSet,
|
||||
notificationEndpointsAdd: configurationActionSet,
|
||||
notificationEndpointsAddAny: configurationActionSet,
|
||||
tiers: configurationActionSet,
|
||||
tiersAdd: configurationActionSet,
|
||||
tiersAddAny: configurationActionSet,
|
||||
users: usersActionSet,
|
||||
usersDetail: usersActionSet,
|
||||
groups: groupsActionSet,
|
||||
groupsDetails: groupsActionSet,
|
||||
iamPolicies: iamPoliciesActionSet,
|
||||
policiesDetail: iamPoliciesActionSet,
|
||||
dashboard: dashboardActionSet,
|
||||
metrics: dashboardActionSet,
|
||||
profiling: profilingActionSet,
|
||||
buckets: bucketsActionSet,
|
||||
bucketsGeneral: bucketsActionSet,
|
||||
bucketsAdmin: bucketsActionSet,
|
||||
bucketsAdminMain: bucketsActionSet,
|
||||
serviceAccounts: serviceAccountsActionSet,
|
||||
changePassword: changePasswordActionSet,
|
||||
remoteBuckets: remoteBucketsActionSet,
|
||||
replication: replicationActionSet,
|
||||
bucketsBrowser: objectBrowserActionSet,
|
||||
bucketsBrowserMenu: objectBrowserActionSet,
|
||||
bucketsBrowserList: objectBrowserActionSet,
|
||||
bucketsBrowserMain: objectBrowserActionSet,
|
||||
license: licenseActionSet,
|
||||
watch: watchActionSet,
|
||||
heal: healActionSet,
|
||||
trace: traceActionSet,
|
||||
logs: logsActionSet,
|
||||
auditLogs: logsActionSet,
|
||||
tools: toolsActionSet,
|
||||
healthInfo: healthInfoActionSet,
|
||||
}
|
||||
|
||||
// operatorRules contains the mapping between endpoints and ActionSets for operator only mode
|
||||
var operatorRules = map[string]ConfigurationActionSet{
|
||||
tenants: tenantsActionSet,
|
||||
tenantsAdd: tenantsActionSet,
|
||||
tenantsAddSub: tenantsActionSet,
|
||||
tenantsDetail: tenantsActionSet,
|
||||
tenantHop: tenantsActionSet,
|
||||
tenantsDetailSummary: tenantsActionSet,
|
||||
tenantsDetailMetrics: tenantsActionSet,
|
||||
tenantsDetailPods: tenantsActionSet,
|
||||
tenantsDetailPools: tenantsActionSet,
|
||||
tenantsDetailVolumes: tenantsActionSet,
|
||||
tenantsDetailLicense: tenantsActionSet,
|
||||
tenantsDetailSecurity: tenantsActionSet,
|
||||
podsDetail: tenantsActionSet,
|
||||
storage: storageActionSet,
|
||||
storageDrives: storageActionSet,
|
||||
storageVolumes: storageActionSet,
|
||||
license: licenseActionSet,
|
||||
}
|
||||
|
||||
// operatorOnly ENV variable
|
||||
var operatorOnly = GetOperatorMode()
|
||||
|
||||
// GetActionsStringFromPolicy extract the admin/s3 actions from a given policy and return them in []string format
|
||||
//
|
||||
// ie:
|
||||
// {
|
||||
// "Version": "2012-10-17",
|
||||
// "Statement": [{
|
||||
// "Action": [
|
||||
// "admin:ServerInfo",
|
||||
// "admin:CreatePolicy",
|
||||
// "admin:GetUser"
|
||||
// ],
|
||||
// ...
|
||||
// },
|
||||
// {
|
||||
// "Action": [
|
||||
// "s3:ListenBucketNotification",
|
||||
// "s3:PutBucketNotification"
|
||||
// ],
|
||||
// ...
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// Will produce an array like: ["admin:ServerInfo", "admin:CreatePolicy", "admin:GetUser", "s3:ListenBucketNotification", "s3:PutBucketNotification"]\
|
||||
func GetActionsStringFromPolicy(policy *iampolicy.Policy) []string {
|
||||
var actions []string
|
||||
for _, statement := range policy.Statements {
|
||||
// We only care about allowed actions
|
||||
if statement.Effect.IsAllowed(true) {
|
||||
for _, action := range statement.Actions.ToSlice() {
|
||||
actions = append(actions, string(action))
|
||||
}
|
||||
}
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
// actionsStringToActionSet convert a given string array to iampolicy.ActionSet structure
|
||||
// this avoids ending with duplicate actions
|
||||
func actionsStringToActionSet(actions []string) iampolicy.ActionSet {
|
||||
actionsSet := iampolicy.ActionSet{}
|
||||
for _, action := range actions {
|
||||
actionsSet.Add(iampolicy.Action(action))
|
||||
}
|
||||
return actionsSet
|
||||
}
|
||||
|
||||
// GetAuthorizedEndpoints return a list of allowed endpoint based on a provided *iampolicy.Policy
|
||||
// ie: pages the user should have access based on his current privileges
|
||||
func GetAuthorizedEndpoints(actions []string) []string {
|
||||
rangeTake := endpointRules
|
||||
|
||||
if operatorOnly {
|
||||
rangeTake = operatorRules
|
||||
}
|
||||
// Prepare new ActionSet structure that will hold all the user actions
|
||||
userAllowedAction := actionsStringToActionSet(actions)
|
||||
var allowedEndpoints []string
|
||||
for endpoint, rules := range rangeTake {
|
||||
|
||||
// check if display rule exists for this endpoint, this will control
|
||||
// what user sees on the console UI
|
||||
if rule, ok := displayRules[endpoint]; ok {
|
||||
if rule != nil && !rule() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// check if user policy matches s3:* or admin:* typesIntersection
|
||||
endpointActionTypes := rules.actionTypes
|
||||
typesIntersection := endpointActionTypes.Intersection(userAllowedAction)
|
||||
if len(typesIntersection) == len(endpointActionTypes.ToSlice()) {
|
||||
allowedEndpoints = append(allowedEndpoints, endpoint)
|
||||
continue
|
||||
}
|
||||
// check if user policy matches explicitly defined endpoint required actions
|
||||
endpointRequiredActions := rules.actions
|
||||
actionsIntersection := endpointRequiredActions.Intersection(userAllowedAction)
|
||||
if len(actionsIntersection) == len(endpointRequiredActions.ToSlice()) {
|
||||
allowedEndpoints = append(allowedEndpoints, endpoint)
|
||||
}
|
||||
}
|
||||
return allowedEndpoints
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
// 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 acl
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type args struct {
|
||||
actions []string
|
||||
}
|
||||
|
||||
type endpoint struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
}
|
||||
|
||||
func validateEndpoints(t *testing.T, configs []endpoint) {
|
||||
for _, tt := range configs {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GetAuthorizedEndpoints(tt.args.actions); !reflect.DeepEqual(len(got), tt.want) {
|
||||
t.Errorf("GetAuthorizedEndpoints() = %v, want %v", len(got), tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAuthorizedEndpoints(t *testing.T) {
|
||||
tests := []endpoint{
|
||||
{
|
||||
name: "dashboard endpoint",
|
||||
args: args{
|
||||
[]string{"admin:ServerInfo"},
|
||||
},
|
||||
want: 9,
|
||||
},
|
||||
{
|
||||
name: "policies endpoint",
|
||||
args: args{
|
||||
[]string{
|
||||
"admin:CreatePolicy",
|
||||
"admin:DeletePolicy",
|
||||
"admin:GetPolicy",
|
||||
"admin:AttachUserOrGroupPolicy",
|
||||
"admin:ListUserPolicies",
|
||||
},
|
||||
},
|
||||
want: 9,
|
||||
},
|
||||
{
|
||||
name: "all admin endpoints",
|
||||
args: args{
|
||||
[]string{
|
||||
"admin:*",
|
||||
},
|
||||
},
|
||||
want: 33,
|
||||
},
|
||||
{
|
||||
name: "all s3 endpoints",
|
||||
args: args{
|
||||
[]string{
|
||||
"s3:*",
|
||||
},
|
||||
},
|
||||
want: 9,
|
||||
},
|
||||
{
|
||||
name: "all admin and s3 endpoints",
|
||||
args: args{
|
||||
[]string{
|
||||
"admin:*",
|
||||
"s3:*",
|
||||
},
|
||||
},
|
||||
want: 35,
|
||||
},
|
||||
{
|
||||
name: "Console User - default endpoints",
|
||||
args: args{
|
||||
[]string{},
|
||||
},
|
||||
want: 7,
|
||||
},
|
||||
}
|
||||
|
||||
validateEndpoints(t, tests)
|
||||
}
|
||||
|
||||
func TestOperatorOnlyEndpoints(t *testing.T) {
|
||||
operatorOnly = true
|
||||
|
||||
tests := []endpoint{
|
||||
{
|
||||
name: "Operator Only - all admin endpoints",
|
||||
args: args{},
|
||||
want: 17,
|
||||
},
|
||||
}
|
||||
|
||||
validateEndpoints(t, tests)
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
// This file is part of MinIO Orchestrator
|
||||
// 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 acl
|
||||
|
||||
import iampolicy "github.com/minio/pkg/iam/policy"
|
||||
|
||||
var BucketViewerRole = iampolicy.NewActionSet(
|
||||
iampolicy.ListBucketAction,
|
||||
iampolicy.GetObjectAction,
|
||||
)
|
||||
|
||||
var BucketEditorRole = iampolicy.NewActionSet(
|
||||
iampolicy.ListBucketAction,
|
||||
iampolicy.GetObjectAction,
|
||||
iampolicy.DeleteObjectAction,
|
||||
iampolicy.PutObjectAction,
|
||||
)
|
||||
var BucketAdminRole = iampolicy.NewActionSet(
|
||||
iampolicy.AbortMultipartUploadAction,
|
||||
iampolicy.CreateBucketAction,
|
||||
iampolicy.DeleteBucketAction,
|
||||
iampolicy.ForceDeleteBucketAction,
|
||||
iampolicy.DeleteBucketPolicyAction,
|
||||
iampolicy.GetBucketLocationAction,
|
||||
iampolicy.GetBucketNotificationAction,
|
||||
iampolicy.GetBucketPolicyAction,
|
||||
iampolicy.HeadBucketAction,
|
||||
iampolicy.ListAllMyBucketsAction,
|
||||
iampolicy.GetBucketPolicyStatusAction,
|
||||
iampolicy.ListBucketVersionsAction,
|
||||
iampolicy.ListBucketMultipartUploadsAction,
|
||||
iampolicy.ListenNotificationAction,
|
||||
iampolicy.ListenBucketNotificationAction,
|
||||
iampolicy.ListMultipartUploadPartsAction,
|
||||
iampolicy.PutBucketLifecycleAction,
|
||||
iampolicy.GetBucketLifecycleAction,
|
||||
iampolicy.PutBucketNotificationAction,
|
||||
iampolicy.PutBucketPolicyAction,
|
||||
iampolicy.BypassGovernanceRetentionAction,
|
||||
iampolicy.PutObjectRetentionAction,
|
||||
iampolicy.GetObjectRetentionAction,
|
||||
iampolicy.GetObjectLegalHoldAction,
|
||||
iampolicy.PutObjectLegalHoldAction,
|
||||
iampolicy.GetBucketObjectLockConfigurationAction,
|
||||
iampolicy.PutBucketObjectLockConfigurationAction,
|
||||
iampolicy.GetBucketTaggingAction,
|
||||
iampolicy.PutBucketTaggingAction,
|
||||
iampolicy.GetObjectVersionAction,
|
||||
iampolicy.GetObjectVersionTaggingAction,
|
||||
iampolicy.DeleteObjectVersionAction,
|
||||
iampolicy.DeleteObjectVersionTaggingAction,
|
||||
iampolicy.PutObjectVersionTaggingAction,
|
||||
iampolicy.GetObjectTaggingAction,
|
||||
iampolicy.PutObjectTaggingAction,
|
||||
iampolicy.DeleteObjectTaggingAction,
|
||||
iampolicy.PutBucketEncryptionAction,
|
||||
iampolicy.GetBucketEncryptionAction,
|
||||
iampolicy.PutBucketVersioningAction,
|
||||
iampolicy.GetBucketVersioningAction,
|
||||
iampolicy.GetReplicationConfigurationAction,
|
||||
iampolicy.PutReplicationConfigurationAction,
|
||||
iampolicy.ReplicateObjectAction,
|
||||
iampolicy.ReplicateDeleteAction,
|
||||
iampolicy.ReplicateTagsAction,
|
||||
iampolicy.GetObjectVersionForReplicationAction,
|
||||
iampolicy.AllActions,
|
||||
)
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
|
||||
@@ -20,8 +20,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/minio/console/pkg/auth/idp/oauth2"
|
||||
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
xoauth2 "golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// IdentityProviderI interface with all functions to be implemented
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
// that are used within this project.
|
||||
type IdentityProviderI interface {
|
||||
VerifyIdentity(ctx context.Context, code, state string) (*credentials.Credentials, error)
|
||||
VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error)
|
||||
GenerateLoginURL() string
|
||||
}
|
||||
|
||||
@@ -45,6 +46,11 @@ func (c IdentityProvider) VerifyIdentity(ctx context.Context, code, state string
|
||||
return c.Client.VerifyIdentity(ctx, code, state)
|
||||
}
|
||||
|
||||
// VerifyIdentityForOperator will verify the user identity against the idp using the authorization code flow
|
||||
func (c IdentityProvider) VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error) {
|
||||
return c.Client.VerifyIdentityForOperator(ctx, code, state)
|
||||
}
|
||||
|
||||
// GenerateLoginURL returns a new URL used by the user to login against the idp
|
||||
func (c IdentityProvider) GenerateLoginURL() string {
|
||||
return c.Client.GenerateLoginURL()
|
||||
|
||||
@@ -45,15 +45,19 @@ func GetIDPSecret() string {
|
||||
return env.Get(ConsoleIDPSecret, "")
|
||||
}
|
||||
|
||||
// Public endpoint used by the identity oidcProvider when redirecting the user after identity verification
|
||||
// Public endpoint used by the identity oidcProvider when redirecting
|
||||
// the user after identity verification
|
||||
func GetIDPCallbackURL() string {
|
||||
return env.Get(ConsoleIDPCallbackURL, "")
|
||||
}
|
||||
|
||||
func GetIDPCallbackURLDynamic() bool {
|
||||
return env.Get(ConsoleIDPCallbackURLDynamic, "") == "on"
|
||||
}
|
||||
|
||||
func IsIDPEnabled() bool {
|
||||
return GetIDPURL() != "" &&
|
||||
GetIDPClientID() != "" &&
|
||||
GetIDPCallbackURL() != ""
|
||||
GetIDPClientID() != ""
|
||||
}
|
||||
|
||||
var defaultPassphraseForIDPHmac = utils.RandomCharString(64)
|
||||
|
||||
@@ -18,14 +18,15 @@ package oauth2
|
||||
|
||||
// Environment constants for console IDP/SSO configuration
|
||||
const (
|
||||
ConsoleMinIOServer = "CONSOLE_MINIO_SERVER"
|
||||
ConsoleIDPURL = "CONSOLE_IDP_URL"
|
||||
ConsoleIDPClientID = "CONSOLE_IDP_CLIENT_ID"
|
||||
ConsoleIDPSecret = "CONSOLE_IDP_SECRET"
|
||||
ConsoleIDPCallbackURL = "CONSOLE_IDP_CALLBACK"
|
||||
ConsoleIDPHmacPassphrase = "CONSOLE_IDP_HMAC_PASSPHRASE"
|
||||
ConsoleIDPHmacSalt = "CONSOLE_IDP_HMAC_SALT"
|
||||
ConsoleIDPScopes = "CONSOLE_IDP_SCOPES"
|
||||
ConsoleIDPUserInfo = "CONSOLE_IDP_USERINFO"
|
||||
ConsoleIDPTokenExpiration = "CONSOLE_IDP_TOKEN_EXPIRATION"
|
||||
ConsoleMinIOServer = "CONSOLE_MINIO_SERVER"
|
||||
ConsoleIDPURL = "CONSOLE_IDP_URL"
|
||||
ConsoleIDPClientID = "CONSOLE_IDP_CLIENT_ID"
|
||||
ConsoleIDPSecret = "CONSOLE_IDP_SECRET"
|
||||
ConsoleIDPCallbackURL = "CONSOLE_IDP_CALLBACK"
|
||||
ConsoleIDPCallbackURLDynamic = "CONSOLE_IDP_CALLBACK_DYNAMIC"
|
||||
ConsoleIDPHmacPassphrase = "CONSOLE_IDP_HMAC_PASSPHRASE"
|
||||
ConsoleIDPHmacSalt = "CONSOLE_IDP_HMAC_SALT"
|
||||
ConsoleIDPScopes = "CONSOLE_IDP_SCOPES"
|
||||
ConsoleIDPUserInfo = "CONSOLE_IDP_USERINFO"
|
||||
ConsoleIDPTokenExpiration = "CONSOLE_IDP_TOKEN_EXPIRATION"
|
||||
)
|
||||
|
||||
@@ -119,11 +119,33 @@ var derivedKey = func() []byte {
|
||||
return pbkdf2.Key([]byte(getPassphraseForIDPHmac()), []byte(getSaltForIDPHmac()), 4096, 32, sha1.New)
|
||||
}
|
||||
|
||||
const (
|
||||
schemeHTTP = "http"
|
||||
schemeHTTPS = "https"
|
||||
)
|
||||
|
||||
func getLoginCallbackURL(r *http.Request) string {
|
||||
scheme := getSourceScheme(r)
|
||||
if scheme == "" {
|
||||
if r.TLS != nil {
|
||||
scheme = schemeHTTPS
|
||||
} else {
|
||||
scheme = schemeHTTP
|
||||
}
|
||||
}
|
||||
|
||||
redirectURL := scheme + "://" + r.Host + "/oauth_callback"
|
||||
_, err := url.Parse(redirectURL)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redirectURL
|
||||
}
|
||||
|
||||
// NewOauth2ProviderClient instantiates a new oauth2 client using the configured credentials
|
||||
// it returns a *Provider object that contains the necessary configuration to initiate an
|
||||
// oauth2 authentication flow
|
||||
func NewOauth2ProviderClient(scopes []string, httpClient *http.Client) (*Provider, error) {
|
||||
|
||||
func NewOauth2ProviderClient(scopes []string, r *http.Request, httpClient *http.Client) (*Provider, error) {
|
||||
ddoc, err := parseDiscoveryDoc(GetIDPURL(), httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -134,6 +156,13 @@ func NewOauth2ProviderClient(scopes []string, httpClient *http.Client) (*Provide
|
||||
scopes = strings.Split(getIDPScopes(), ",")
|
||||
}
|
||||
|
||||
redirectURL := GetIDPCallbackURL()
|
||||
if GetIDPCallbackURLDynamic() {
|
||||
// dynamic redirect if set, will generate redirect URLs
|
||||
// dynamically based on incoming requests.
|
||||
redirectURL = getLoginCallbackURL(r)
|
||||
}
|
||||
|
||||
// add "openid" scope always.
|
||||
scopes = append(scopes, "openid")
|
||||
|
||||
@@ -141,7 +170,7 @@ func NewOauth2ProviderClient(scopes []string, httpClient *http.Client) (*Provide
|
||||
client.oauth2Config = &xoauth2.Config{
|
||||
ClientID: GetIDPClientID(),
|
||||
ClientSecret: GetIDPSecret(),
|
||||
RedirectURL: GetIDPCallbackURL(),
|
||||
RedirectURL: redirectURL,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: ddoc.AuthEndpoint,
|
||||
TokenURL: ddoc.TokenEndpoint,
|
||||
@@ -181,7 +210,8 @@ type User struct {
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// VerifyIdentity will contact the configured IDP and validate the user identity based on the authorization code
|
||||
// VerifyIdentity will contact the configured IDP to the user identity based on the authorization code and state
|
||||
// if the user is valid, then it will contact MinIO to get valid sts credentials based on the identity provided by the IDP
|
||||
func (client *Provider) VerifyIdentity(ctx context.Context, code, state string) (*credentials.Credentials, error) {
|
||||
// verify the provided state is valid (prevents CSRF attacks)
|
||||
if err := validateOauth2State(state); err != nil {
|
||||
@@ -232,6 +262,23 @@ func (client *Provider) VerifyIdentity(ctx context.Context, code, state string)
|
||||
return sts, nil
|
||||
}
|
||||
|
||||
// VerifyIdentityForOperator will contact the configured IDP and validate the user identity based on the authorization code and state
|
||||
func (client *Provider) VerifyIdentityForOperator(ctx context.Context, code, state string) (*xoauth2.Token, error) {
|
||||
// verify the provided state is valid (prevents CSRF attacks)
|
||||
if err := validateOauth2State(state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
customCtx := context.WithValue(ctx, oauth2.HTTPClient, client.provHTTPClient)
|
||||
oauth2Token, err := client.oauth2Config.Exchange(customCtx, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !oauth2Token.Valid() {
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
return oauth2Token, nil
|
||||
}
|
||||
|
||||
// validateOauth2State validates the provided state was originated using the same
|
||||
// instance (or one configured using the same secrets) of Console, this is basically used to prevent CSRF attacks
|
||||
// https://security.stackexchange.com/questions/20187/oauth2-cross-site-request-forgery-and-state-parameter
|
||||
|
||||
70
pkg/auth/idp/oauth2/proxy.go
Normal file
70
pkg/auth/idp/oauth2/proxy.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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 oauth2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// De-facto standard header keys.
|
||||
xForwardedProto = http.CanonicalHeaderKey("X-Forwarded-Proto")
|
||||
xForwardedScheme = http.CanonicalHeaderKey("X-Forwarded-Scheme")
|
||||
)
|
||||
|
||||
var (
|
||||
// RFC7239 defines a new "Forwarded: " header designed to replace the
|
||||
// existing use of X-Forwarded-* headers.
|
||||
// e.g. Forwarded: for=192.0.2.60;proto=https;by=203.0.113.43
|
||||
forwarded = http.CanonicalHeaderKey("Forwarded")
|
||||
// Allows for a sub-match of the first value after 'for=' to the next
|
||||
// comma, semi-colon or space. The match is case-insensitive.
|
||||
forRegex = regexp.MustCompile(`(?i)(?:for=)([^(;|,| )]+)(.*)`)
|
||||
// Allows for a sub-match for the first instance of scheme (http|https)
|
||||
// prefixed by 'proto='. The match is case-insensitive.
|
||||
protoRegex = regexp.MustCompile(`(?i)^(;|,| )+(?:proto=)(https|http)`)
|
||||
)
|
||||
|
||||
// getSourceScheme retrieves the scheme from the X-Forwarded-Proto and RFC7239
|
||||
// Forwarded headers (in that order).
|
||||
func getSourceScheme(r *http.Request) string {
|
||||
var scheme string
|
||||
|
||||
// Retrieve the scheme from X-Forwarded-Proto.
|
||||
if proto := r.Header.Get(xForwardedProto); proto != "" {
|
||||
scheme = strings.ToLower(proto)
|
||||
} else if proto = r.Header.Get(xForwardedScheme); proto != "" {
|
||||
scheme = strings.ToLower(proto)
|
||||
} else if proto := r.Header.Get(forwarded); proto != "" {
|
||||
// match should contain at least two elements if the protocol was
|
||||
// specified in the Forwarded header. The first element will always be
|
||||
// the 'for=', which we ignore, subsequently we proceed to look for
|
||||
// 'proto=' which should precede right after `for=` if not
|
||||
// we simply ignore the values and return empty. This is in line
|
||||
// with the approach we took for returning first ip from multiple
|
||||
// params.
|
||||
if match := forRegex.FindStringSubmatch(proto); len(match) > 1 {
|
||||
if match = protoRegex.FindStringSubmatch(match[2]); len(match) > 1 {
|
||||
scheme = strings.ToLower(match[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return scheme
|
||||
}
|
||||
@@ -54,7 +54,7 @@ var derivedKey = func() []byte {
|
||||
return pbkdf2.Key([]byte(token.GetPBKDFPassphrase()), []byte(token.GetPBKDFSalt()), 4096, 32, sha1.New)
|
||||
}
|
||||
|
||||
// IsSessionTokenValid returns true or false depending if the provided session token is valid or not
|
||||
// IsSessionTokenValid returns true or false depending upon the provided session if the token is valid or not
|
||||
func IsSessionTokenValid(token string) bool {
|
||||
_, err := SessionTokenAuthenticate(token)
|
||||
return err == nil
|
||||
|
||||
@@ -17,17 +17,25 @@
|
||||
package token
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/minio/console/pkg/auth/utils"
|
||||
"github.com/minio/pkg/env"
|
||||
)
|
||||
|
||||
// ConsoleSTSDurationSeconds returns the default session duration for the STS requested tokens.
|
||||
func GetConsoleSTSDurationInSeconds() int {
|
||||
duration, err := strconv.Atoi(env.Get(ConsoleSTSDurationSeconds, "3600"))
|
||||
// GetConsoleSTSDuration returns the default session duration for the STS requested tokens (defaults to 1h)
|
||||
func GetConsoleSTSDuration() time.Duration {
|
||||
durationSeconds := env.Get(ConsoleSTSDurationSeconds, "")
|
||||
if durationSeconds != "" {
|
||||
duration, err := time.ParseDuration(durationSeconds + "s")
|
||||
if err != nil {
|
||||
duration = 1 * time.Hour
|
||||
}
|
||||
return duration
|
||||
}
|
||||
duration, err := time.ParseDuration(env.Get(ConsoleSTSDuration, "1h"))
|
||||
if err != nil {
|
||||
duration = 3600
|
||||
duration = 1 * time.Hour
|
||||
}
|
||||
return duration
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
package token
|
||||
|
||||
const (
|
||||
ConsoleSTSDurationSeconds = "CONSOLE_STS_DURATION_SECONDS"
|
||||
ConsoleSTSDurationSeconds = "CONSOLE_STS_DURATION_SECONDS" // (deprecated), set value in seconds for sts session, ie: 3600
|
||||
ConsoleSTSDuration = "CONSOLE_STS_DURATION" // time.Duration format, ie: 3600s, 2h45m, 1h, etc
|
||||
ConsolePBKDFPassphrase = "CONSOLE_PBKDF_PASSPHRASE"
|
||||
ConsolePBKDFSalt = "CONSOLE_PBKDF_SALT"
|
||||
)
|
||||
|
||||
@@ -1,23 +1,335 @@
|
||||
{
|
||||
"files": {
|
||||
"static/js/0.13617cf4.chunk.js": "./static/js/0.13617cf4.chunk.js",
|
||||
"static/js/0.13617cf4.chunk.js.map": "./static/js/0.13617cf4.chunk.js.map",
|
||||
"static/js/1.0be45f9d.chunk.js": "./static/js/1.0be45f9d.chunk.js",
|
||||
"static/js/1.0be45f9d.chunk.js.map": "./static/js/1.0be45f9d.chunk.js.map",
|
||||
"static/js/2.c6332ba2.chunk.js": "./static/js/2.c6332ba2.chunk.js",
|
||||
"static/js/2.c6332ba2.chunk.js.map": "./static/js/2.c6332ba2.chunk.js.map",
|
||||
"static/js/3.c27e235b.chunk.js": "./static/js/3.c27e235b.chunk.js",
|
||||
"static/js/3.c27e235b.chunk.js.map": "./static/js/3.c27e235b.chunk.js.map",
|
||||
"static/js/4.86bf098f.chunk.js": "./static/js/4.86bf098f.chunk.js",
|
||||
"static/js/4.86bf098f.chunk.js.map": "./static/js/4.86bf098f.chunk.js.map",
|
||||
"static/js/5.5b6acde5.chunk.js": "./static/js/5.5b6acde5.chunk.js",
|
||||
"static/js/5.5b6acde5.chunk.js.map": "./static/js/5.5b6acde5.chunk.js.map",
|
||||
"static/css/6.5cffa46b.chunk.css": "./static/css/6.5cffa46b.chunk.css",
|
||||
"static/js/6.3dc1e022.chunk.js": "./static/js/6.3dc1e022.chunk.js",
|
||||
"static/js/6.3dc1e022.chunk.js.map": "./static/js/6.3dc1e022.chunk.js.map",
|
||||
"static/js/7.922fea77.chunk.js": "./static/js/7.922fea77.chunk.js",
|
||||
"static/js/7.922fea77.chunk.js.map": "./static/js/7.922fea77.chunk.js.map",
|
||||
"static/js/8.54376882.chunk.js": "./static/js/8.54376882.chunk.js",
|
||||
"static/js/8.54376882.chunk.js.map": "./static/js/8.54376882.chunk.js.map",
|
||||
"static/js/9.47354616.chunk.js": "./static/js/9.47354616.chunk.js",
|
||||
"static/js/9.47354616.chunk.js.map": "./static/js/9.47354616.chunk.js.map",
|
||||
"static/js/10.823cb77b.chunk.js": "./static/js/10.823cb77b.chunk.js",
|
||||
"static/js/10.823cb77b.chunk.js.map": "./static/js/10.823cb77b.chunk.js.map",
|
||||
"static/js/11.3ec67190.chunk.js": "./static/js/11.3ec67190.chunk.js",
|
||||
"static/js/11.3ec67190.chunk.js.map": "./static/js/11.3ec67190.chunk.js.map",
|
||||
"static/js/12.9a9417a8.chunk.js": "./static/js/12.9a9417a8.chunk.js",
|
||||
"static/js/12.9a9417a8.chunk.js.map": "./static/js/12.9a9417a8.chunk.js.map",
|
||||
"static/js/13.454a3b89.chunk.js": "./static/js/13.454a3b89.chunk.js",
|
||||
"static/js/13.454a3b89.chunk.js.map": "./static/js/13.454a3b89.chunk.js.map",
|
||||
"static/js/14.f767e520.chunk.js": "./static/js/14.f767e520.chunk.js",
|
||||
"static/js/14.f767e520.chunk.js.map": "./static/js/14.f767e520.chunk.js.map",
|
||||
"main.css": "./static/css/main.ed78990a.chunk.css",
|
||||
"main.js": "./static/js/main.894c8129.chunk.js",
|
||||
"main.js.map": "./static/js/main.894c8129.chunk.js.map",
|
||||
"runtime-main.js": "./static/js/runtime-main.30f8243a.js",
|
||||
"runtime-main.js.map": "./static/js/runtime-main.30f8243a.js.map",
|
||||
"static/css/2.71021f35.chunk.css": "./static/css/2.71021f35.chunk.css",
|
||||
"static/js/2.0aaf1c4d.chunk.js": "./static/js/2.0aaf1c4d.chunk.js",
|
||||
"static/js/2.0aaf1c4d.chunk.js.map": "./static/js/2.0aaf1c4d.chunk.js.map",
|
||||
"main.js": "./static/js/main.f80ccd0f.chunk.js",
|
||||
"main.js.map": "./static/js/main.f80ccd0f.chunk.js.map",
|
||||
"runtime-main.js": "./static/js/runtime-main.fcab880c.js",
|
||||
"runtime-main.js.map": "./static/js/runtime-main.fcab880c.js.map",
|
||||
"static/js/17.8e73fe21.chunk.js": "./static/js/17.8e73fe21.chunk.js",
|
||||
"static/js/17.8e73fe21.chunk.js.map": "./static/js/17.8e73fe21.chunk.js.map",
|
||||
"static/js/18.4af62807.chunk.js": "./static/js/18.4af62807.chunk.js",
|
||||
"static/js/18.4af62807.chunk.js.map": "./static/js/18.4af62807.chunk.js.map",
|
||||
"static/css/19.ae75e1bf.chunk.css": "./static/css/19.ae75e1bf.chunk.css",
|
||||
"static/js/19.ccd4c180.chunk.js": "./static/js/19.ccd4c180.chunk.js",
|
||||
"static/js/19.ccd4c180.chunk.js.map": "./static/js/19.ccd4c180.chunk.js.map",
|
||||
"static/js/20.7c1f2689.chunk.js": "./static/js/20.7c1f2689.chunk.js",
|
||||
"static/js/20.7c1f2689.chunk.js.map": "./static/js/20.7c1f2689.chunk.js.map",
|
||||
"static/js/21.5a7a3798.chunk.js": "./static/js/21.5a7a3798.chunk.js",
|
||||
"static/js/21.5a7a3798.chunk.js.map": "./static/js/21.5a7a3798.chunk.js.map",
|
||||
"static/js/22.55a393ba.chunk.js": "./static/js/22.55a393ba.chunk.js",
|
||||
"static/js/22.55a393ba.chunk.js.map": "./static/js/22.55a393ba.chunk.js.map",
|
||||
"static/css/23.5cffa46b.chunk.css": "./static/css/23.5cffa46b.chunk.css",
|
||||
"static/js/23.a23f0e32.chunk.js": "./static/js/23.a23f0e32.chunk.js",
|
||||
"static/js/23.a23f0e32.chunk.js.map": "./static/js/23.a23f0e32.chunk.js.map",
|
||||
"static/js/24.238468ef.chunk.js": "./static/js/24.238468ef.chunk.js",
|
||||
"static/js/24.238468ef.chunk.js.map": "./static/js/24.238468ef.chunk.js.map",
|
||||
"static/js/25.970ec4f6.chunk.js": "./static/js/25.970ec4f6.chunk.js",
|
||||
"static/js/25.970ec4f6.chunk.js.map": "./static/js/25.970ec4f6.chunk.js.map",
|
||||
"static/js/26.0d80212c.chunk.js": "./static/js/26.0d80212c.chunk.js",
|
||||
"static/js/26.0d80212c.chunk.js.map": "./static/js/26.0d80212c.chunk.js.map",
|
||||
"static/js/27.2275ed9e.chunk.js": "./static/js/27.2275ed9e.chunk.js",
|
||||
"static/js/27.2275ed9e.chunk.js.map": "./static/js/27.2275ed9e.chunk.js.map",
|
||||
"static/css/28.5cffa46b.chunk.css": "./static/css/28.5cffa46b.chunk.css",
|
||||
"static/js/28.8a8c9ef6.chunk.js": "./static/js/28.8a8c9ef6.chunk.js",
|
||||
"static/js/28.8a8c9ef6.chunk.js.map": "./static/js/28.8a8c9ef6.chunk.js.map",
|
||||
"static/js/29.6179f6fe.chunk.js": "./static/js/29.6179f6fe.chunk.js",
|
||||
"static/js/29.6179f6fe.chunk.js.map": "./static/js/29.6179f6fe.chunk.js.map",
|
||||
"static/js/30.285674fb.chunk.js": "./static/js/30.285674fb.chunk.js",
|
||||
"static/js/30.285674fb.chunk.js.map": "./static/js/30.285674fb.chunk.js.map",
|
||||
"static/js/31.4d44099b.chunk.js": "./static/js/31.4d44099b.chunk.js",
|
||||
"static/js/31.4d44099b.chunk.js.map": "./static/js/31.4d44099b.chunk.js.map",
|
||||
"static/js/32.f3087518.chunk.js": "./static/js/32.f3087518.chunk.js",
|
||||
"static/js/32.f3087518.chunk.js.map": "./static/js/32.f3087518.chunk.js.map",
|
||||
"static/js/33.221549d8.chunk.js": "./static/js/33.221549d8.chunk.js",
|
||||
"static/js/33.221549d8.chunk.js.map": "./static/js/33.221549d8.chunk.js.map",
|
||||
"static/js/34.8d388bec.chunk.js": "./static/js/34.8d388bec.chunk.js",
|
||||
"static/js/34.8d388bec.chunk.js.map": "./static/js/34.8d388bec.chunk.js.map",
|
||||
"static/js/35.09762103.chunk.js": "./static/js/35.09762103.chunk.js",
|
||||
"static/js/35.09762103.chunk.js.map": "./static/js/35.09762103.chunk.js.map",
|
||||
"static/js/36.e9974d39.chunk.js": "./static/js/36.e9974d39.chunk.js",
|
||||
"static/js/36.e9974d39.chunk.js.map": "./static/js/36.e9974d39.chunk.js.map",
|
||||
"static/js/37.4cff4f82.chunk.js": "./static/js/37.4cff4f82.chunk.js",
|
||||
"static/js/37.4cff4f82.chunk.js.map": "./static/js/37.4cff4f82.chunk.js.map",
|
||||
"static/js/38.fcbbc7af.chunk.js": "./static/js/38.fcbbc7af.chunk.js",
|
||||
"static/js/38.fcbbc7af.chunk.js.map": "./static/js/38.fcbbc7af.chunk.js.map",
|
||||
"static/js/39.e9ba480e.chunk.js": "./static/js/39.e9ba480e.chunk.js",
|
||||
"static/js/39.e9ba480e.chunk.js.map": "./static/js/39.e9ba480e.chunk.js.map",
|
||||
"static/js/40.0402c10a.chunk.js": "./static/js/40.0402c10a.chunk.js",
|
||||
"static/js/40.0402c10a.chunk.js.map": "./static/js/40.0402c10a.chunk.js.map",
|
||||
"static/js/41.0db168ff.chunk.js": "./static/js/41.0db168ff.chunk.js",
|
||||
"static/js/41.0db168ff.chunk.js.map": "./static/js/41.0db168ff.chunk.js.map",
|
||||
"static/js/42.ea8f424b.chunk.js": "./static/js/42.ea8f424b.chunk.js",
|
||||
"static/js/42.ea8f424b.chunk.js.map": "./static/js/42.ea8f424b.chunk.js.map",
|
||||
"static/js/43.47e2e8d4.chunk.js": "./static/js/43.47e2e8d4.chunk.js",
|
||||
"static/js/43.47e2e8d4.chunk.js.map": "./static/js/43.47e2e8d4.chunk.js.map",
|
||||
"static/js/44.327385ac.chunk.js": "./static/js/44.327385ac.chunk.js",
|
||||
"static/js/44.327385ac.chunk.js.map": "./static/js/44.327385ac.chunk.js.map",
|
||||
"static/js/45.45cee628.chunk.js": "./static/js/45.45cee628.chunk.js",
|
||||
"static/js/45.45cee628.chunk.js.map": "./static/js/45.45cee628.chunk.js.map",
|
||||
"static/js/46.1a95c251.chunk.js": "./static/js/46.1a95c251.chunk.js",
|
||||
"static/js/46.1a95c251.chunk.js.map": "./static/js/46.1a95c251.chunk.js.map",
|
||||
"static/js/47.97130e63.chunk.js": "./static/js/47.97130e63.chunk.js",
|
||||
"static/js/47.97130e63.chunk.js.map": "./static/js/47.97130e63.chunk.js.map",
|
||||
"static/js/48.bcd0e339.chunk.js": "./static/js/48.bcd0e339.chunk.js",
|
||||
"static/js/48.bcd0e339.chunk.js.map": "./static/js/48.bcd0e339.chunk.js.map",
|
||||
"static/js/49.ade67f9e.chunk.js": "./static/js/49.ade67f9e.chunk.js",
|
||||
"static/js/49.ade67f9e.chunk.js.map": "./static/js/49.ade67f9e.chunk.js.map",
|
||||
"static/js/50.a757b16e.chunk.js": "./static/js/50.a757b16e.chunk.js",
|
||||
"static/js/50.a757b16e.chunk.js.map": "./static/js/50.a757b16e.chunk.js.map",
|
||||
"static/js/51.cd6a5193.chunk.js": "./static/js/51.cd6a5193.chunk.js",
|
||||
"static/js/51.cd6a5193.chunk.js.map": "./static/js/51.cd6a5193.chunk.js.map",
|
||||
"static/js/52.2128ace5.chunk.js": "./static/js/52.2128ace5.chunk.js",
|
||||
"static/js/52.2128ace5.chunk.js.map": "./static/js/52.2128ace5.chunk.js.map",
|
||||
"static/js/53.ccb1dc9d.chunk.js": "./static/js/53.ccb1dc9d.chunk.js",
|
||||
"static/js/53.ccb1dc9d.chunk.js.map": "./static/js/53.ccb1dc9d.chunk.js.map",
|
||||
"static/js/54.048945c1.chunk.js": "./static/js/54.048945c1.chunk.js",
|
||||
"static/js/54.048945c1.chunk.js.map": "./static/js/54.048945c1.chunk.js.map",
|
||||
"static/js/55.46c76f97.chunk.js": "./static/js/55.46c76f97.chunk.js",
|
||||
"static/js/55.46c76f97.chunk.js.map": "./static/js/55.46c76f97.chunk.js.map",
|
||||
"static/js/56.c6be919f.chunk.js": "./static/js/56.c6be919f.chunk.js",
|
||||
"static/js/56.c6be919f.chunk.js.map": "./static/js/56.c6be919f.chunk.js.map",
|
||||
"static/js/57.68863c0d.chunk.js": "./static/js/57.68863c0d.chunk.js",
|
||||
"static/js/57.68863c0d.chunk.js.map": "./static/js/57.68863c0d.chunk.js.map",
|
||||
"static/js/58.ddc4ad34.chunk.js": "./static/js/58.ddc4ad34.chunk.js",
|
||||
"static/js/58.ddc4ad34.chunk.js.map": "./static/js/58.ddc4ad34.chunk.js.map",
|
||||
"static/js/59.beac03a1.chunk.js": "./static/js/59.beac03a1.chunk.js",
|
||||
"static/js/59.beac03a1.chunk.js.map": "./static/js/59.beac03a1.chunk.js.map",
|
||||
"static/js/60.06e239ba.chunk.js": "./static/js/60.06e239ba.chunk.js",
|
||||
"static/js/60.06e239ba.chunk.js.map": "./static/js/60.06e239ba.chunk.js.map",
|
||||
"static/js/61.ad8ae9b9.chunk.js": "./static/js/61.ad8ae9b9.chunk.js",
|
||||
"static/js/61.ad8ae9b9.chunk.js.map": "./static/js/61.ad8ae9b9.chunk.js.map",
|
||||
"static/js/62.c6f82d61.chunk.js": "./static/js/62.c6f82d61.chunk.js",
|
||||
"static/js/62.c6f82d61.chunk.js.map": "./static/js/62.c6f82d61.chunk.js.map",
|
||||
"static/js/63.cb07c443.chunk.js": "./static/js/63.cb07c443.chunk.js",
|
||||
"static/js/63.cb07c443.chunk.js.map": "./static/js/63.cb07c443.chunk.js.map",
|
||||
"static/js/64.477153ab.chunk.js": "./static/js/64.477153ab.chunk.js",
|
||||
"static/js/64.477153ab.chunk.js.map": "./static/js/64.477153ab.chunk.js.map",
|
||||
"static/js/65.a5db341c.chunk.js": "./static/js/65.a5db341c.chunk.js",
|
||||
"static/js/65.a5db341c.chunk.js.map": "./static/js/65.a5db341c.chunk.js.map",
|
||||
"static/js/66.6f5359b7.chunk.js": "./static/js/66.6f5359b7.chunk.js",
|
||||
"static/js/66.6f5359b7.chunk.js.map": "./static/js/66.6f5359b7.chunk.js.map",
|
||||
"static/js/67.2f3acc30.chunk.js": "./static/js/67.2f3acc30.chunk.js",
|
||||
"static/js/67.2f3acc30.chunk.js.map": "./static/js/67.2f3acc30.chunk.js.map",
|
||||
"static/js/68.e0ba0794.chunk.js": "./static/js/68.e0ba0794.chunk.js",
|
||||
"static/js/68.e0ba0794.chunk.js.map": "./static/js/68.e0ba0794.chunk.js.map",
|
||||
"static/js/69.05a6714e.chunk.js": "./static/js/69.05a6714e.chunk.js",
|
||||
"static/js/69.05a6714e.chunk.js.map": "./static/js/69.05a6714e.chunk.js.map",
|
||||
"static/js/70.3ba7eb63.chunk.js": "./static/js/70.3ba7eb63.chunk.js",
|
||||
"static/js/70.3ba7eb63.chunk.js.map": "./static/js/70.3ba7eb63.chunk.js.map",
|
||||
"static/js/71.bfd0d3b5.chunk.js": "./static/js/71.bfd0d3b5.chunk.js",
|
||||
"static/js/71.bfd0d3b5.chunk.js.map": "./static/js/71.bfd0d3b5.chunk.js.map",
|
||||
"static/js/72.4e53641b.chunk.js": "./static/js/72.4e53641b.chunk.js",
|
||||
"static/js/72.4e53641b.chunk.js.map": "./static/js/72.4e53641b.chunk.js.map",
|
||||
"static/js/73.07dbe173.chunk.js": "./static/js/73.07dbe173.chunk.js",
|
||||
"static/js/73.07dbe173.chunk.js.map": "./static/js/73.07dbe173.chunk.js.map",
|
||||
"static/js/74.1c7c59eb.chunk.js": "./static/js/74.1c7c59eb.chunk.js",
|
||||
"static/js/74.1c7c59eb.chunk.js.map": "./static/js/74.1c7c59eb.chunk.js.map",
|
||||
"static/js/75.d705d043.chunk.js": "./static/js/75.d705d043.chunk.js",
|
||||
"static/js/75.d705d043.chunk.js.map": "./static/js/75.d705d043.chunk.js.map",
|
||||
"static/js/76.b07fe449.chunk.js": "./static/js/76.b07fe449.chunk.js",
|
||||
"static/js/76.b07fe449.chunk.js.map": "./static/js/76.b07fe449.chunk.js.map",
|
||||
"static/js/77.4e0b1d75.chunk.js": "./static/js/77.4e0b1d75.chunk.js",
|
||||
"static/js/77.4e0b1d75.chunk.js.map": "./static/js/77.4e0b1d75.chunk.js.map",
|
||||
"static/js/78.68dd0cda.chunk.js": "./static/js/78.68dd0cda.chunk.js",
|
||||
"static/js/78.68dd0cda.chunk.js.map": "./static/js/78.68dd0cda.chunk.js.map",
|
||||
"static/js/79.68caff87.chunk.js": "./static/js/79.68caff87.chunk.js",
|
||||
"static/js/79.68caff87.chunk.js.map": "./static/js/79.68caff87.chunk.js.map",
|
||||
"static/js/80.d8f14863.chunk.js": "./static/js/80.d8f14863.chunk.js",
|
||||
"static/js/80.d8f14863.chunk.js.map": "./static/js/80.d8f14863.chunk.js.map",
|
||||
"static/js/81.a21ec1b4.chunk.js": "./static/js/81.a21ec1b4.chunk.js",
|
||||
"static/js/81.a21ec1b4.chunk.js.map": "./static/js/81.a21ec1b4.chunk.js.map",
|
||||
"static/js/82.a7fd7f77.chunk.js": "./static/js/82.a7fd7f77.chunk.js",
|
||||
"static/js/82.a7fd7f77.chunk.js.map": "./static/js/82.a7fd7f77.chunk.js.map",
|
||||
"static/js/83.975f3d96.chunk.js": "./static/js/83.975f3d96.chunk.js",
|
||||
"static/js/83.975f3d96.chunk.js.map": "./static/js/83.975f3d96.chunk.js.map",
|
||||
"static/js/84.90c895d2.chunk.js": "./static/js/84.90c895d2.chunk.js",
|
||||
"static/js/84.90c895d2.chunk.js.map": "./static/js/84.90c895d2.chunk.js.map",
|
||||
"static/js/85.4d067b6d.chunk.js": "./static/js/85.4d067b6d.chunk.js",
|
||||
"static/js/85.4d067b6d.chunk.js.map": "./static/js/85.4d067b6d.chunk.js.map",
|
||||
"static/js/86.01244dbe.chunk.js": "./static/js/86.01244dbe.chunk.js",
|
||||
"static/js/86.01244dbe.chunk.js.map": "./static/js/86.01244dbe.chunk.js.map",
|
||||
"static/js/87.9e274b84.chunk.js": "./static/js/87.9e274b84.chunk.js",
|
||||
"static/js/87.9e274b84.chunk.js.map": "./static/js/87.9e274b84.chunk.js.map",
|
||||
"static/js/88.ca3ee480.chunk.js": "./static/js/88.ca3ee480.chunk.js",
|
||||
"static/js/88.ca3ee480.chunk.js.map": "./static/js/88.ca3ee480.chunk.js.map",
|
||||
"static/js/89.dfa5addf.chunk.js": "./static/js/89.dfa5addf.chunk.js",
|
||||
"static/js/89.dfa5addf.chunk.js.map": "./static/js/89.dfa5addf.chunk.js.map",
|
||||
"static/js/90.cac27752.chunk.js": "./static/js/90.cac27752.chunk.js",
|
||||
"static/js/90.cac27752.chunk.js.map": "./static/js/90.cac27752.chunk.js.map",
|
||||
"static/js/91.6f0c5cbc.chunk.js": "./static/js/91.6f0c5cbc.chunk.js",
|
||||
"static/js/91.6f0c5cbc.chunk.js.map": "./static/js/91.6f0c5cbc.chunk.js.map",
|
||||
"static/js/92.9a103f02.chunk.js": "./static/js/92.9a103f02.chunk.js",
|
||||
"static/js/92.9a103f02.chunk.js.map": "./static/js/92.9a103f02.chunk.js.map",
|
||||
"static/js/93.1c3aab06.chunk.js": "./static/js/93.1c3aab06.chunk.js",
|
||||
"static/js/93.1c3aab06.chunk.js.map": "./static/js/93.1c3aab06.chunk.js.map",
|
||||
"static/js/94.cf4d38ae.chunk.js": "./static/js/94.cf4d38ae.chunk.js",
|
||||
"static/js/94.cf4d38ae.chunk.js.map": "./static/js/94.cf4d38ae.chunk.js.map",
|
||||
"static/js/95.2b73d679.chunk.js": "./static/js/95.2b73d679.chunk.js",
|
||||
"static/js/95.2b73d679.chunk.js.map": "./static/js/95.2b73d679.chunk.js.map",
|
||||
"static/js/96.de52525f.chunk.js": "./static/js/96.de52525f.chunk.js",
|
||||
"static/js/96.de52525f.chunk.js.map": "./static/js/96.de52525f.chunk.js.map",
|
||||
"static/js/97.fa5e9d94.chunk.js": "./static/js/97.fa5e9d94.chunk.js",
|
||||
"static/js/97.fa5e9d94.chunk.js.map": "./static/js/97.fa5e9d94.chunk.js.map",
|
||||
"static/js/98.5f5d5abb.chunk.js": "./static/js/98.5f5d5abb.chunk.js",
|
||||
"static/js/98.5f5d5abb.chunk.js.map": "./static/js/98.5f5d5abb.chunk.js.map",
|
||||
"static/js/99.690ab63b.chunk.js": "./static/js/99.690ab63b.chunk.js",
|
||||
"static/js/99.690ab63b.chunk.js.map": "./static/js/99.690ab63b.chunk.js.map",
|
||||
"static/js/100.4c02eb74.chunk.js": "./static/js/100.4c02eb74.chunk.js",
|
||||
"static/js/100.4c02eb74.chunk.js.map": "./static/js/100.4c02eb74.chunk.js.map",
|
||||
"static/js/101.137ad8fc.chunk.js": "./static/js/101.137ad8fc.chunk.js",
|
||||
"static/js/101.137ad8fc.chunk.js.map": "./static/js/101.137ad8fc.chunk.js.map",
|
||||
"static/js/102.dea0eebf.chunk.js": "./static/js/102.dea0eebf.chunk.js",
|
||||
"static/js/102.dea0eebf.chunk.js.map": "./static/js/102.dea0eebf.chunk.js.map",
|
||||
"static/js/103.cd531ec0.chunk.js": "./static/js/103.cd531ec0.chunk.js",
|
||||
"static/js/103.cd531ec0.chunk.js.map": "./static/js/103.cd531ec0.chunk.js.map",
|
||||
"static/js/104.42f5f8a7.chunk.js": "./static/js/104.42f5f8a7.chunk.js",
|
||||
"static/js/104.42f5f8a7.chunk.js.map": "./static/js/104.42f5f8a7.chunk.js.map",
|
||||
"static/js/105.498c84c6.chunk.js": "./static/js/105.498c84c6.chunk.js",
|
||||
"static/js/105.498c84c6.chunk.js.map": "./static/js/105.498c84c6.chunk.js.map",
|
||||
"static/js/106.db10af44.chunk.js": "./static/js/106.db10af44.chunk.js",
|
||||
"static/js/106.db10af44.chunk.js.map": "./static/js/106.db10af44.chunk.js.map",
|
||||
"static/js/107.b7f47f73.chunk.js": "./static/js/107.b7f47f73.chunk.js",
|
||||
"static/js/107.b7f47f73.chunk.js.map": "./static/js/107.b7f47f73.chunk.js.map",
|
||||
"static/js/108.cf2e7390.chunk.js": "./static/js/108.cf2e7390.chunk.js",
|
||||
"static/js/108.cf2e7390.chunk.js.map": "./static/js/108.cf2e7390.chunk.js.map",
|
||||
"static/js/109.6b326008.chunk.js": "./static/js/109.6b326008.chunk.js",
|
||||
"static/js/109.6b326008.chunk.js.map": "./static/js/109.6b326008.chunk.js.map",
|
||||
"static/js/110.b496fe71.chunk.js": "./static/js/110.b496fe71.chunk.js",
|
||||
"static/js/110.b496fe71.chunk.js.map": "./static/js/110.b496fe71.chunk.js.map",
|
||||
"static/js/111.ed1fb13c.chunk.js": "./static/js/111.ed1fb13c.chunk.js",
|
||||
"static/js/111.ed1fb13c.chunk.js.map": "./static/js/111.ed1fb13c.chunk.js.map",
|
||||
"static/js/112.83d07fdd.chunk.js": "./static/js/112.83d07fdd.chunk.js",
|
||||
"static/js/112.83d07fdd.chunk.js.map": "./static/js/112.83d07fdd.chunk.js.map",
|
||||
"static/js/113.4101a53f.chunk.js": "./static/js/113.4101a53f.chunk.js",
|
||||
"static/js/113.4101a53f.chunk.js.map": "./static/js/113.4101a53f.chunk.js.map",
|
||||
"static/js/114.9d7115bf.chunk.js": "./static/js/114.9d7115bf.chunk.js",
|
||||
"static/js/114.9d7115bf.chunk.js.map": "./static/js/114.9d7115bf.chunk.js.map",
|
||||
"static/js/115.bb343ca4.chunk.js": "./static/js/115.bb343ca4.chunk.js",
|
||||
"static/js/115.bb343ca4.chunk.js.map": "./static/js/115.bb343ca4.chunk.js.map",
|
||||
"static/js/116.2836c700.chunk.js": "./static/js/116.2836c700.chunk.js",
|
||||
"static/js/116.2836c700.chunk.js.map": "./static/js/116.2836c700.chunk.js.map",
|
||||
"static/js/117.40d18a46.chunk.js": "./static/js/117.40d18a46.chunk.js",
|
||||
"static/js/117.40d18a46.chunk.js.map": "./static/js/117.40d18a46.chunk.js.map",
|
||||
"static/js/118.d3062752.chunk.js": "./static/js/118.d3062752.chunk.js",
|
||||
"static/js/118.d3062752.chunk.js.map": "./static/js/118.d3062752.chunk.js.map",
|
||||
"static/js/119.37ab7a9d.chunk.js": "./static/js/119.37ab7a9d.chunk.js",
|
||||
"static/js/119.37ab7a9d.chunk.js.map": "./static/js/119.37ab7a9d.chunk.js.map",
|
||||
"static/js/120.11e571b5.chunk.js": "./static/js/120.11e571b5.chunk.js",
|
||||
"static/js/120.11e571b5.chunk.js.map": "./static/js/120.11e571b5.chunk.js.map",
|
||||
"static/js/121.de75799a.chunk.js": "./static/js/121.de75799a.chunk.js",
|
||||
"static/js/121.de75799a.chunk.js.map": "./static/js/121.de75799a.chunk.js.map",
|
||||
"static/js/122.94a3b938.chunk.js": "./static/js/122.94a3b938.chunk.js",
|
||||
"static/js/122.94a3b938.chunk.js.map": "./static/js/122.94a3b938.chunk.js.map",
|
||||
"static/js/123.e4bf8145.chunk.js": "./static/js/123.e4bf8145.chunk.js",
|
||||
"static/js/123.e4bf8145.chunk.js.map": "./static/js/123.e4bf8145.chunk.js.map",
|
||||
"static/js/124.90cf8f49.chunk.js": "./static/js/124.90cf8f49.chunk.js",
|
||||
"static/js/124.90cf8f49.chunk.js.map": "./static/js/124.90cf8f49.chunk.js.map",
|
||||
"static/js/125.135bcd7e.chunk.js": "./static/js/125.135bcd7e.chunk.js",
|
||||
"static/js/125.135bcd7e.chunk.js.map": "./static/js/125.135bcd7e.chunk.js.map",
|
||||
"static/js/126.b4c65ba4.chunk.js": "./static/js/126.b4c65ba4.chunk.js",
|
||||
"static/js/126.b4c65ba4.chunk.js.map": "./static/js/126.b4c65ba4.chunk.js.map",
|
||||
"static/js/127.56757c79.chunk.js": "./static/js/127.56757c79.chunk.js",
|
||||
"static/js/127.56757c79.chunk.js.map": "./static/js/127.56757c79.chunk.js.map",
|
||||
"static/js/128.4e5dd374.chunk.js": "./static/js/128.4e5dd374.chunk.js",
|
||||
"static/js/128.4e5dd374.chunk.js.map": "./static/js/128.4e5dd374.chunk.js.map",
|
||||
"static/js/129.8f47c817.chunk.js": "./static/js/129.8f47c817.chunk.js",
|
||||
"static/js/129.8f47c817.chunk.js.map": "./static/js/129.8f47c817.chunk.js.map",
|
||||
"static/js/130.425b5bc5.chunk.js": "./static/js/130.425b5bc5.chunk.js",
|
||||
"static/js/130.425b5bc5.chunk.js.map": "./static/js/130.425b5bc5.chunk.js.map",
|
||||
"static/js/131.aeadff3b.chunk.js": "./static/js/131.aeadff3b.chunk.js",
|
||||
"static/js/131.aeadff3b.chunk.js.map": "./static/js/131.aeadff3b.chunk.js.map",
|
||||
"static/js/132.8ca12ce9.chunk.js": "./static/js/132.8ca12ce9.chunk.js",
|
||||
"static/js/132.8ca12ce9.chunk.js.map": "./static/js/132.8ca12ce9.chunk.js.map",
|
||||
"static/js/133.931544d3.chunk.js": "./static/js/133.931544d3.chunk.js",
|
||||
"static/js/133.931544d3.chunk.js.map": "./static/js/133.931544d3.chunk.js.map",
|
||||
"static/js/134.54e505ac.chunk.js": "./static/js/134.54e505ac.chunk.js",
|
||||
"static/js/134.54e505ac.chunk.js.map": "./static/js/134.54e505ac.chunk.js.map",
|
||||
"static/js/135.eb72e5fd.chunk.js": "./static/js/135.eb72e5fd.chunk.js",
|
||||
"static/js/135.eb72e5fd.chunk.js.map": "./static/js/135.eb72e5fd.chunk.js.map",
|
||||
"static/js/136.aa415e8d.chunk.js": "./static/js/136.aa415e8d.chunk.js",
|
||||
"static/js/136.aa415e8d.chunk.js.map": "./static/js/136.aa415e8d.chunk.js.map",
|
||||
"static/js/137.57fcbb8d.chunk.js": "./static/js/137.57fcbb8d.chunk.js",
|
||||
"static/js/137.57fcbb8d.chunk.js.map": "./static/js/137.57fcbb8d.chunk.js.map",
|
||||
"static/js/138.a296c474.chunk.js": "./static/js/138.a296c474.chunk.js",
|
||||
"static/js/138.a296c474.chunk.js.map": "./static/js/138.a296c474.chunk.js.map",
|
||||
"static/js/139.96da1da4.chunk.js": "./static/js/139.96da1da4.chunk.js",
|
||||
"static/js/139.96da1da4.chunk.js.map": "./static/js/139.96da1da4.chunk.js.map",
|
||||
"static/js/140.67291f02.chunk.js": "./static/js/140.67291f02.chunk.js",
|
||||
"static/js/140.67291f02.chunk.js.map": "./static/js/140.67291f02.chunk.js.map",
|
||||
"static/js/141.237a74b9.chunk.js": "./static/js/141.237a74b9.chunk.js",
|
||||
"static/js/141.237a74b9.chunk.js.map": "./static/js/141.237a74b9.chunk.js.map",
|
||||
"static/js/142.67d82a1e.chunk.js": "./static/js/142.67d82a1e.chunk.js",
|
||||
"static/js/142.67d82a1e.chunk.js.map": "./static/js/142.67d82a1e.chunk.js.map",
|
||||
"static/js/143.a14b2164.chunk.js": "./static/js/143.a14b2164.chunk.js",
|
||||
"static/js/143.a14b2164.chunk.js.map": "./static/js/143.a14b2164.chunk.js.map",
|
||||
"static/js/144.48a07121.chunk.js": "./static/js/144.48a07121.chunk.js",
|
||||
"static/js/144.48a07121.chunk.js.map": "./static/js/144.48a07121.chunk.js.map",
|
||||
"static/js/145.b1b3d335.chunk.js": "./static/js/145.b1b3d335.chunk.js",
|
||||
"static/js/145.b1b3d335.chunk.js.map": "./static/js/145.b1b3d335.chunk.js.map",
|
||||
"static/js/146.f04f92e4.chunk.js": "./static/js/146.f04f92e4.chunk.js",
|
||||
"static/js/146.f04f92e4.chunk.js.map": "./static/js/146.f04f92e4.chunk.js.map",
|
||||
"static/js/147.0a995fa2.chunk.js": "./static/js/147.0a995fa2.chunk.js",
|
||||
"static/js/147.0a995fa2.chunk.js.map": "./static/js/147.0a995fa2.chunk.js.map",
|
||||
"static/js/148.96ef8835.chunk.js": "./static/js/148.96ef8835.chunk.js",
|
||||
"static/js/148.96ef8835.chunk.js.map": "./static/js/148.96ef8835.chunk.js.map",
|
||||
"static/js/149.56337ce7.chunk.js": "./static/js/149.56337ce7.chunk.js",
|
||||
"static/js/149.56337ce7.chunk.js.map": "./static/js/149.56337ce7.chunk.js.map",
|
||||
"static/js/150.ffd0054b.chunk.js": "./static/js/150.ffd0054b.chunk.js",
|
||||
"static/js/150.ffd0054b.chunk.js.map": "./static/js/150.ffd0054b.chunk.js.map",
|
||||
"static/js/151.7cc43483.chunk.js": "./static/js/151.7cc43483.chunk.js",
|
||||
"static/js/151.7cc43483.chunk.js.map": "./static/js/151.7cc43483.chunk.js.map",
|
||||
"index.html": "./index.html",
|
||||
"static/css/2.71021f35.chunk.css.map": "./static/css/2.71021f35.chunk.css.map",
|
||||
"static/css/19.ae75e1bf.chunk.css.map": "./static/css/19.ae75e1bf.chunk.css.map",
|
||||
"static/css/23.5cffa46b.chunk.css.map": "./static/css/23.5cffa46b.chunk.css.map",
|
||||
"static/css/28.5cffa46b.chunk.css.map": "./static/css/28.5cffa46b.chunk.css.map",
|
||||
"static/css/6.5cffa46b.chunk.css.map": "./static/css/6.5cffa46b.chunk.css.map",
|
||||
"static/css/main.ed78990a.chunk.css.map": "./static/css/main.ed78990a.chunk.css.map",
|
||||
"static/js/2.0aaf1c4d.chunk.js.LICENSE.txt": "./static/js/2.0aaf1c4d.chunk.js.LICENSE.txt"
|
||||
"static/js/17.8e73fe21.chunk.js.LICENSE.txt": "./static/js/17.8e73fe21.chunk.js.LICENSE.txt",
|
||||
"static/js/18.4af62807.chunk.js.LICENSE.txt": "./static/js/18.4af62807.chunk.js.LICENSE.txt",
|
||||
"static/js/19.ccd4c180.chunk.js.LICENSE.txt": "./static/js/19.ccd4c180.chunk.js.LICENSE.txt",
|
||||
"static/js/20.7c1f2689.chunk.js.LICENSE.txt": "./static/js/20.7c1f2689.chunk.js.LICENSE.txt",
|
||||
"static/js/21.5a7a3798.chunk.js.LICENSE.txt": "./static/js/21.5a7a3798.chunk.js.LICENSE.txt",
|
||||
"static/js/22.55a393ba.chunk.js.LICENSE.txt": "./static/js/22.55a393ba.chunk.js.LICENSE.txt",
|
||||
"static/js/27.2275ed9e.chunk.js.LICENSE.txt": "./static/js/27.2275ed9e.chunk.js.LICENSE.txt",
|
||||
"static/js/3.c27e235b.chunk.js.LICENSE.txt": "./static/js/3.c27e235b.chunk.js.LICENSE.txt",
|
||||
"static/js/7.922fea77.chunk.js.LICENSE.txt": "./static/js/7.922fea77.chunk.js.LICENSE.txt"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.30f8243a.js",
|
||||
"static/css/2.71021f35.chunk.css",
|
||||
"static/js/2.0aaf1c4d.chunk.js",
|
||||
"static/js/runtime-main.fcab880c.js",
|
||||
"static/css/19.ae75e1bf.chunk.css",
|
||||
"static/js/19.ccd4c180.chunk.js",
|
||||
"static/css/main.ed78990a.chunk.css",
|
||||
"static/js/main.894c8129.chunk.js"
|
||||
"static/js/main.f80ccd0f.chunk.js"
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/css/19.ae75e1bf.chunk.css
Normal file
2
portal-ui/build/static/css/19.ae75e1bf.chunk.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.ReactVirtualized__Table__headerRow{font-weight:700;text-transform:uppercase}.ReactVirtualized__Table__headerRow,.ReactVirtualized__Table__row{display:flex;flex-direction:row;align-items:center}.ReactVirtualized__Table__headerTruncatedText{display:inline-block;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ReactVirtualized__Table__headerColumn,.ReactVirtualized__Table__rowColumn{margin-right:10px;min-width:0}.ReactVirtualized__Table__rowColumn{text-overflow:ellipsis;white-space:nowrap}.ReactVirtualized__Table__headerColumn:first-of-type,.ReactVirtualized__Table__rowColumn:first-of-type{margin-left:10px}.ReactVirtualized__Table__sortableHeaderColumn{cursor:pointer}.ReactVirtualized__Table__sortableHeaderIconContainer{display:flex;align-items:center}.ReactVirtualized__Table__sortableHeaderIcon{flex:0 0 24px;height:1em;width:1em;fill:currentColor}.react-grid-layout{position:relative;transition:height .2s ease}.react-grid-item{transition:all .2s ease;transition-property:left,top}.react-grid-item img{pointer-events:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.react-grid-item.cssTransforms{transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform}.react-grid-item.resizing{z-index:1;will-change:width,height}.react-grid-item.react-draggable-dragging{transition:none;z-index:3;will-change:transform}.react-grid-item.dropping{visibility:hidden}.react-grid-item.react-grid-placeholder{background:red;opacity:.2;transition-duration:.1s;z-index:2;-webkit-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.react-grid-item>.react-resizable-handle{position:absolute;width:20px;height:20px}.react-grid-item>.react-resizable-handle:after{content:"";position:absolute;right:3px;bottom:3px;width:5px;height:5px;border-right:2px solid rgba(0,0,0,.4);border-bottom:2px solid rgba(0,0,0,.4)}.react-resizable-hide>.react-resizable-handle{display:none}.react-grid-item>.react-resizable-handle.react-resizable-handle-sw{bottom:0;left:0;cursor:sw-resize;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-se{bottom:0;right:0;cursor:se-resize}.react-grid-item>.react-resizable-handle.react-resizable-handle-nw{top:0;left:0;cursor:nw-resize;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-ne{top:0;right:0;cursor:ne-resize;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-e,.react-grid-item>.react-resizable-handle.react-resizable-handle-w{top:50%;margin-top:-10px;cursor:ew-resize}.react-grid-item>.react-resizable-handle.react-resizable-handle-w{left:0;-webkit-transform:rotate(135deg);transform:rotate(135deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-e{right:0;-webkit-transform:rotate(315deg);transform:rotate(315deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-n,.react-grid-item>.react-resizable-handle.react-resizable-handle-s{left:50%;margin-left:-10px;cursor:ns-resize}.react-grid-item>.react-resizable-handle.react-resizable-handle-n{top:0;-webkit-transform:rotate(225deg);transform:rotate(225deg)}.react-grid-item>.react-resizable-handle.react-resizable-handle-s{bottom:0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.react-resizable{position:relative}.react-resizable-handle{position:absolute;width:20px;height:20px;background-repeat:no-repeat;background-origin:content-box;box-sizing:border-box;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgd2lkdGg9IjYiIGhlaWdodD0iNiI+PHBhdGggZD0iTTYgNkgwVjQuMmg0LjJWMEg2djZ6IiBvcGFjaXR5PSIuMzAyIi8+PC9zdmc+");background-position:100% 100%;padding:0 3px 3px 0}.react-resizable-handle-sw{bottom:0;left:0;cursor:sw-resize;-webkit-transform:rotate(90deg);transform:rotate(90deg)}.react-resizable-handle-se{bottom:0;right:0;cursor:se-resize}.react-resizable-handle-nw{top:0;left:0;cursor:nw-resize;-webkit-transform:rotate(180deg);transform:rotate(180deg)}.react-resizable-handle-ne{top:0;right:0;cursor:ne-resize;-webkit-transform:rotate(270deg);transform:rotate(270deg)}.react-resizable-handle-e,.react-resizable-handle-w{top:50%;margin-top:-10px;cursor:ew-resize}.react-resizable-handle-w{left:0;-webkit-transform:rotate(135deg);transform:rotate(135deg)}.react-resizable-handle-e{right:0;-webkit-transform:rotate(315deg);transform:rotate(315deg)}.react-resizable-handle-n,.react-resizable-handle-s{left:50%;margin-left:-10px;cursor:ns-resize}.react-resizable-handle-n{top:0;-webkit-transform:rotate(225deg);transform:rotate(225deg)}.react-resizable-handle-s{bottom:0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}
|
||||
/*# sourceMappingURL=19.ae75e1bf.chunk.css.map */
|
||||
1
portal-ui/build/static/css/19.ae75e1bf.chunk.css.map
Normal file
1
portal-ui/build/static/css/19.ae75e1bf.chunk.css.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/css/23.5cffa46b.chunk.css
Normal file
2
portal-ui/build/static/css/23.5cffa46b.chunk.css
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/css/23.5cffa46b.chunk.css.map
Normal file
1
portal-ui/build/static/css/23.5cffa46b.chunk.css.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/css/28.5cffa46b.chunk.css
Normal file
2
portal-ui/build/static/css/28.5cffa46b.chunk.css
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/css/28.5cffa46b.chunk.css.map
Normal file
1
portal-ui/build/static/css/28.5cffa46b.chunk.css.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/css/6.5cffa46b.chunk.css
Normal file
2
portal-ui/build/static/css/6.5cffa46b.chunk.css
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/css/6.5cffa46b.chunk.css.map
Normal file
1
portal-ui/build/static/css/6.5cffa46b.chunk.css.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/0.13617cf4.chunk.js
Normal file
2
portal-ui/build/static/js/0.13617cf4.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/0.13617cf4.chunk.js.map
Normal file
1
portal-ui/build/static/js/0.13617cf4.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/1.0be45f9d.chunk.js
Normal file
2
portal-ui/build/static/js/1.0be45f9d.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/1.0be45f9d.chunk.js.map
Normal file
1
portal-ui/build/static/js/1.0be45f9d.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/10.823cb77b.chunk.js
Normal file
2
portal-ui/build/static/js/10.823cb77b.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/10.823cb77b.chunk.js.map
Normal file
1
portal-ui/build/static/js/10.823cb77b.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/100.4c02eb74.chunk.js
Normal file
2
portal-ui/build/static/js/100.4c02eb74.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/100.4c02eb74.chunk.js.map
Normal file
1
portal-ui/build/static/js/100.4c02eb74.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/101.137ad8fc.chunk.js
Normal file
2
portal-ui/build/static/js/101.137ad8fc.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/101.137ad8fc.chunk.js.map
Normal file
1
portal-ui/build/static/js/101.137ad8fc.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/102.dea0eebf.chunk.js
Normal file
2
portal-ui/build/static/js/102.dea0eebf.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/102.dea0eebf.chunk.js.map
Normal file
1
portal-ui/build/static/js/102.dea0eebf.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/103.cd531ec0.chunk.js
Normal file
2
portal-ui/build/static/js/103.cd531ec0.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/103.cd531ec0.chunk.js.map
Normal file
1
portal-ui/build/static/js/103.cd531ec0.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/104.42f5f8a7.chunk.js
Normal file
2
portal-ui/build/static/js/104.42f5f8a7.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/104.42f5f8a7.chunk.js.map
Normal file
1
portal-ui/build/static/js/104.42f5f8a7.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/105.498c84c6.chunk.js
Normal file
2
portal-ui/build/static/js/105.498c84c6.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/105.498c84c6.chunk.js.map
Normal file
1
portal-ui/build/static/js/105.498c84c6.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/106.db10af44.chunk.js
Normal file
2
portal-ui/build/static/js/106.db10af44.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/106.db10af44.chunk.js.map
Normal file
1
portal-ui/build/static/js/106.db10af44.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/107.b7f47f73.chunk.js
Normal file
2
portal-ui/build/static/js/107.b7f47f73.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/107.b7f47f73.chunk.js.map
Normal file
1
portal-ui/build/static/js/107.b7f47f73.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/108.cf2e7390.chunk.js
Normal file
2
portal-ui/build/static/js/108.cf2e7390.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/108.cf2e7390.chunk.js.map
Normal file
1
portal-ui/build/static/js/108.cf2e7390.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/109.6b326008.chunk.js
Normal file
2
portal-ui/build/static/js/109.6b326008.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/109.6b326008.chunk.js.map
Normal file
1
portal-ui/build/static/js/109.6b326008.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/11.3ec67190.chunk.js
Normal file
2
portal-ui/build/static/js/11.3ec67190.chunk.js
Normal file
@@ -0,0 +1,2 @@
|
||||
(this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[]).push([[11],{411:function(e,t,n){"use strict";var c=n(1),o=n(2),a=n.n(o),i=n(413),s=n(414),r=n(415),l=n(458),u=n(385),j=n(467),d=n(387),b=n(125),O=n.n(b),f=n(307),m=n(319),p=n(122),x=n(0);t.a=Object(m.a)((function(e){return Object(f.a)(Object(c.a)({},p.h))}))((function(e){var t=e.isOpen,n=void 0!==t&&t,o=e.onClose,b=e.onCancel,f=e.onConfirm,m=e.classes,p=void 0===m?{}:m,v=e.title,h=void 0===v?"":v,C=e.isLoading,k=e.confirmationContent,y=e.cancelText,N=void 0===y?"Cancel":y,g=e.confirmText,P=void 0===g?"Confirm":g,B=e.confirmButtonProps,E=void 0===B?{}:B,T=e.cancelButtonProps,D=void 0===T?{}:T;return Object(x.jsxs)(i.a,{open:n,onClose:function(e,t){"backdropClick"!==t&&o()},className:p.root,sx:{"& .MuiPaper-root":{padding:"1rem 2rem 2rem 1rem"}},children:[Object(x.jsxs)(s.a,{className:p.title,children:[Object(x.jsx)("div",{className:p.titleText,children:h}),Object(x.jsx)("div",{className:p.closeContainer,children:Object(x.jsx)(d.a,{"aria-label":"close",className:p.closeButton,onClick:o,disableRipple:!0,size:"small",children:Object(x.jsx)(O.a,{})})})]}),Object(x.jsx)(r.a,{className:p.content,children:k}),Object(x.jsxs)(l.a,{className:p.actions,children:[Object(x.jsx)(u.a,Object(c.a)(Object(c.a)({className:p.cancelButton,onClick:b||o,disabled:C,type:"button"},D),{},{variant:"outlined",color:"primary",children:N})),Object(x.jsx)(j.a,Object(c.a)(Object(c.a)({className:p.confirmButton,type:"button",onClick:f,loading:C,disabled:C,variant:"outlined",color:"secondary",loadingPosition:"start",startIcon:Object(x.jsx)(a.a.Fragment,{}),autoFocus:!0},E),{},{children:P}))]})]})}))},434:function(e,t,n){"use strict";var c=n(16),o=n(2),a=n(52);t.a=function(e,t){var n=Object(o.useState)(!1),i=Object(c.a)(n,2),s=i[0],r=i[1];return[s,function(n,c,o){r(!0),a.a.invoke(n,c,o).then((function(t){r(!1),e(t)})).catch((function(e){r(!1),t(e)}))}]}},817:function(e,t,n){"use strict";n.r(t);var c=n(16),o=(n(2),n(41)),a=n(466),i=n(32),s=n(434),r=n(411),l=n(0),u={setErrorSnackMessage:i.e},j=Object(o.b)(null,u);t.default=j((function(e){var t=e.closeDeleteModalAndRefresh,n=e.deleteOpen,o=e.selectedPolicy,i=e.setErrorSnackMessage,u=Object(s.a)((function(){return t(!0)}),(function(e){return i(e)})),j=Object(c.a)(u,2),d=j[0],b=j[1];if(!o)return null;return Object(l.jsx)(r.a,{title:"Delete Policy",confirmText:"Delete",isOpen:n,isLoading:d,onConfirm:function(){b("DELETE","/api/v1/policy?name=".concat(o))},onClose:function(){return t(!1)},confirmationContent:Object(l.jsxs)(a.a,{children:["Are you sure you want to delete policy ",Object(l.jsx)("br",{}),Object(l.jsx)("b",{children:o}),"?"]})})}))}}]);
|
||||
//# sourceMappingURL=11.3ec67190.chunk.js.map
|
||||
1
portal-ui/build/static/js/11.3ec67190.chunk.js.map
Normal file
1
portal-ui/build/static/js/11.3ec67190.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/110.b496fe71.chunk.js
Normal file
2
portal-ui/build/static/js/110.b496fe71.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/110.b496fe71.chunk.js.map
Normal file
1
portal-ui/build/static/js/110.b496fe71.chunk.js.map
Normal file
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