Compare commits

...

93 Commits

Author SHA1 Message Date
Daniel Valdivia
78fa499c12 Release v0.12.9 (#1335)
* Release v0.12.9

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* YAMLs

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-17 17:20:29 -08:00
Daniel Valdivia
e03d483d33 Login Improvements (#1334)
* Login Improvements

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Paddings everywhere

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-17 16:30:02 -08:00
Alex
2cc41d56a0 Added font-weight 100 option to Lato fonts (#1333)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-17 15:46:56 -08:00
Alex
99715ff076 Change of render functions for default dashboard (#1330)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-17 17:01:37 -06:00
Prakash Senthil Vel
9c3e8f5bf7 Login UX update (#1328) 2021-12-17 15:21:26 -06:00
Alex
21158e6c7a Added CPU size selector & add tenant cleanup (#1326) 2021-12-17 10:29:10 -08:00
Lenin Alevski
725d6f9691 Handle empty permissions arrays when console runs in operator mode (#1324)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-12-15 10:11:43 -08:00
Alex
dd488e4f7a Created a new API exclusive for metadata information (#1321)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-15 10:50:34 -06:00
Lenin Alevski
3b2c740fe0 Application routing now uses SecureComponent and hasPermission function (#1288)
- Some menu options were not showing even if the user has access to
  perform the operations (IAM Policies)
- Deleted unecessary backend endpoints.go logic, instead using
  SecureComponent to validate application routes and Menu options
  rendering
- All the logic related to routes and permissions is now in the
  permissions.ts file
- Added SecureComponent to List Users page
- Separated Menu options and routing logic for AdminConsole and
  OperatorConsole
- Tools are hidden if user don't have access to them or MinIO is running
  in fs mode (heal, audit log, etc
- Hide change-password button if user don't have access
- Hide create user button if user don't have access
- fixed some bugs when ldap/oidc is enabled

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-12-13 22:37:22 -08:00
Harshavardhana
db5ae3e09f remove random logs from console (#1317)
as a practice always use LogError or LogInfo
instead of using `log.Println()` directly.
2021-12-13 00:17:33 -08:00
Prakash Senthil Vel
8a79409ef6 UX bucket and object modals and all other modals (#1307) 2021-12-10 12:12:46 -08:00
Alex
9444dadc16 Created DistributedOnly component & implemented for Heal & Speedtest pages (#1313)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-10 10:47:54 -08:00
Alex
5618e08bbe Updated ansi-html dependency to fix CVE vulnerability (#1311)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-08 23:22:07 -08:00
Harshavardhana
f4001c0add Release v0.12.8
Signed-off-by: Harshavardhana <harsha@minio.io>
2021-12-08 20:50:50 -08:00
Harshavardhana
02c4910044 update dependencies to allow building 2021-12-08 20:44:00 -08:00
Alex
1713e58e62 Release v0.12.7 (#1310)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-08 19:29:44 -08:00
Daniel Valdivia
90b33bb88f Don't load Menu icons lazily (#1309)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-08 16:09:45 -08:00
Daniel Valdivia
48dfe74aed Fix Console Warnings on Browser (#1306)
* Fixed issues with broken styles

* Fix Merge Conflicts

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* some tweaks

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-08 18:09:29 -06:00
Daniel Valdivia
9b39566f7c Remove Unused CSS Classes (#1308)
* Remove Unused CSS Classes

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Remove Warnings

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-08 15:34:22 -08:00
Daniel Valdivia
aba7a9e1c9 Support to stream video (#1304)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-07 21:36:50 -06:00
adfost
3db22a2479 Rewind mode list directory bug fix (#1297)
* rewind bug fix

* adding constant
2021-12-07 18:01:44 -08:00
Daniel Valdivia
884321cfce Fix Capitalization on Tools Screen (#1305)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-07 17:41:18 -06:00
Daniel Valdivia
20c07a22e3 Remove Rewind Print (#1303)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-07 15:51:01 -06:00
Alex
bf126d3a84 Added fallback to default dashboard in case Prometheus is not accesible (#1302) 2021-12-07 13:39:50 -08:00
Daniel Valdivia
1e59f131e8 Fix 1299: Tools menu not showing for Heal Only Policy (#1301)
* Fix 1299: Tools menu not showing for Heal Only Policy

* Fix caching issue

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-07 15:38:36 -06:00
Prakash Senthil Vel
dfcd49bb5d UX make all delete modals consistent (#1289) 2021-12-07 14:58:38 -06:00
adfost
a7ab26c81e Disallow folders to share the same name as existing files. (#1279) 2021-12-07 14:33:30 -06:00
Alex
35855daa12 Added reset configuration option to settings pages (#1292)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-07 10:41:52 -08:00
Lenin Alevski
3ce0b3d633 Fixed share/download object regression (#1296)
* Fixed share/download object regression
* Adding tests for computeObjectURLWithoutEncode function

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-12-06 15:49:13 -06:00
Alex
569d2390b9 Added option to download selected items in object browser (#1286)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-03 13:10:32 -06:00
Daniel Valdivia
a39e468b96 Release v0.12.6 (#1285)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-02 13:56:50 -08:00
Alex
bbc47e6e11 Added select all to tableWrapper (#1283)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-02 13:05:50 -08:00
Alex
4fb8c2f684 Disabled speedtest in standalone mode (#1278)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-12-01 16:47:29 -08:00
Daniel Valdivia
65dcdc674a Update ViewBox for UploadFolderIcon (#1277)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-01 13:14:08 -08:00
Daniel Valdivia
ebc2b208d2 Icons (#1275)
* Updated Icons

* Tweaks after rebase

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Fix Object Manager Icons

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-12-01 12:07:19 -08:00
Lenin Alevski
b29fc0993b fix: access audit for bucket (#1270)
Policy listing in the Audit list tab was not displaying all the policies
with access to the current bucket

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-30 21:47:54 -08:00
Alex
a3d0cb37a3 Implemented Upload folder functionality (#1272)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-30 21:47:21 -08:00
Harshavardhana
85d549cc51 support all possible conditional values in policies (#1271)
Currently console only support "aws:username" as the
most basic variable for policy evaluation. This PR
extends this to add all the possible combinations
possible.

This includes all `jwt:*` and `ldap:*`
2021-11-30 23:14:55 -06:00
Daniel Valdivia
5f46ec2541 Update Readme screenshots (#1269)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-30 13:52:11 -06:00
Prakash Senthil Vel
9db0c358a4 UX Create New Tenant (#1266) 2021-11-30 13:21:55 -06:00
Harshavardhana
eefc6a7894 reload console certs upon SIGHUP (#1268) 2021-11-30 13:00:46 -06:00
Alex
c529a6d127 Added Object Manager feature for Uploads & downloads (#1265)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-30 12:06:01 -06:00
Prakash Senthil Vel
347c6aba3b Ux Tools screens (#1261)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-27 23:22:06 -08:00
Prakash Senthil Vel
400892565d UX Tiers screen (#1258) 2021-11-27 23:13:47 -08:00
Prakash Senthil Vel
b9873fa471 UX Notification endpoints (#1257)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-25 23:27:24 -06:00
Prakash Senthil Vel
62fe583a21 UX updates to Policy list Bucket and Object List (#1253)
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-25 14:10:23 -08:00
Kaan Kabalak
a69f597f43 Fix z-index of MainError component (#1256)
Fixes #1255
2021-11-24 22:18:00 -06:00
adfost
cdb4392633 Adding Download Directory to Console (#1235)
* Adding Download Directory Functionality

* fixing spaces

* removing unnecessary function

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-24 20:08:25 -08:00
Prakash Senthil Vel
41f77f128e Lazy load components (#1250)
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-24 19:45:09 -08:00
Alex
af68a0c7e4 Release v0.12.5 (#1252)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-23 23:40:02 -08:00
Lenin Alevski
0ea2193878 Adding SecureComponent to policy details page (#1251)
- Make Users & Policies clickeable only if user has permissions to view
  in bucket page
- Add SecureComponent to policy detail page: api calls, menu options,
  raw policy editor, etc.
- Add missing click action to groups in policy detail page
- Fix NPE in list groups for policy endpoint
- Added SecureComponent to ListPolicies page

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-23 20:09:36 -08:00
Prakash Senthil Vel
06b08593b7 Login page UX (#1248) 2021-11-23 13:08:24 -06:00
adfost
6b3ff10027 Securizing bucket tags (#1249) 2021-11-23 11:52:14 -06:00
Daniel Valdivia
53d278a91e Define base for assets and support for sub path (#1247)
* Added correct mime type to files

* Define Base for Assets

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* lint

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Make things relative

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* hop styling

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-22 21:02:16 -08:00
Daniel Valdivia
820fa61b43 Release v0.12.4 (#1246)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 17:46:21 -08:00
Lenin Alevski
3f60df9071 Validate provided external certificates during tenant creation (#1245)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>

Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 16:37:34 -08:00
Daniel Valdivia
0bbd4f0282 Lazy Load Login Screens and Menu Icons (#1244)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 16:12:31 -08:00
Lenin Alevski
1fa4d19e93 Adding secureComponent to groups and buckets description message (#1243)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>

Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 15:55:48 -08:00
Prakash Senthil Vel
f56b4905c9 Settings page ux refactor (#1242)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 15:27:18 -08:00
Daniel Valdivia
575bf2927d Lazy Load All Protected Routes (#1240)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-19 10:30:34 -08:00
Alex
6bacd0a45c Added autotune support to speedtest (#1239)
- Also updated tooltip trigger icon size

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-19 00:08:33 -08:00
Lenin Alevski
7f5de2d70e Adding SecureComponent to list groups and group details page (#1238)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>

Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-18 19:51:40 -08:00
Daniel Valdivia
f0d5398748 Deprecate SvgIcon and make all icons more consistent (#1237)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-18 19:00:37 -06:00
Prakash Senthil Vel
813458c4c1 UX cosmetics for users, groups, service accounts (#1236)
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2021-11-18 15:13:07 -06:00
Lenin Alevski
aae493ac82 Re-implement policy handling in react (#1234)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-18 08:25:01 -08:00
Lenin Alevski
f5234d2830 Simplify admin actions calculations on list buckets (#1233)
* Simplify admin actions calculations on list buckets

* adding license to file
2021-11-15 19:48:25 -06:00
Lenin Alevski
f6acb888d2 Fixed regression on share file endpoint (#1232)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-15 14:13:39 -08:00
Alex
5328f53943 UI Adjustments in share file modal (#1231)
UI Adjustments in share file modal (elements alignment & snackbars position fixes)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-15 15:03:07 -06:00
Prakash Senthil Vel
70a4d76283 Service account ux (#1229)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-15 12:52:55 -08:00
Harshavardhana
373bfbfe3f feat: Support dynamic redirect_uris based on incoming requests (#1227)
To enable this feature you need `CONSOLE_IDP_CALLBACK_DYNAMIC=on`

```
export CONSOLE_IDP_URL=https://gitlab.com/.well-known/openid-configuration
export CONSOLE_IDP_CLIENT_ID="b0088c3836bb029393942f71ed7c8ac0add7f0856e6c86e67b0ff98f85c48658"
export CONSOLE_IDP_SECRET="ed72087b37624e89816ac27c1355420902045274edd7baad2ae29b1b0e8436fe"
export CONSOLE_IDP_SCOPES="openid,profile,email"
export CONSOLE_IDP_USERINFO="on"
export CONSOLE_IDP_CALLBACK_DYNAMIC=on
console srv
```

if this becomes a common practice, we should enable this as default in future.
2021-11-15 12:45:09 -08:00
Daniel Valdivia
b8417fb7a0 fix: policy handling with dynamic policy variables (#1226)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-15 12:24:37 -08:00
Daniel Valdivia
70845c0ec5 Release v0.12.3 (#1224)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-12 18:17:13 -08:00
Daniel Valdivia
21a9073c5e Add HelpBox to DirectCSI. (#1225)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-12 16:38:45 -08:00
Daniel Valdivia
ad240d2ec5 New Bucket Listing Style (#1223)
* New Bucket Listing Style

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Select Multiple Icon

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-12 15:02:54 -08:00
Daniel Valdivia
2b34fbae47 Add Bucket as a page (#1220)
* Add Bucket as a page

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* goimports

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Redirect to bucket browse

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* Address comment

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2021-11-12 12:44:23 -08:00
Prakash Senthil Vel
258a9400d9 New Vertical Tab UX refactor (#1210)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-12 14:26:29 -06:00
Alex
33f13c4853 Changed react-scripts to be only dev dependency (#1222) 2021-11-12 02:12:54 -06:00
adfost
000071e414 Add Tagging for Buckets to Console (#1193) 2021-11-11 18:36:18 -08:00
Alex
3638455abb Increased wide modal size & removed preview file width limit (#1221)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
2021-11-11 16:59:10 -08:00
Alex
8102ab7e35 Added speedtest page & updated diagnostic page (#1099)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-11 16:04:18 -08:00
Lenin Alevski
34dc51a579 Fixed broken oauth2 login for operator (#1217)
This PR includes many fixes and refactors for oauth2 authentication and
login endpoints, ie:

- Invalid login returns `403` instead of `500` error
- Removed the session token from console/operator `user credentials
  login`, `oauth flow login` and `change-password` api responses
- Removed session token from localStorage
- Added styles for oauth_callback page and display more descriptive
  errors for debugging
- Success logins returns `204` instead of `200`
- Removed unused swagger apis and code from both, operator and console
  projects
- Operator `Oauth2` login flow was not validating anything, now it does

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-11 14:46:14 -08:00
jinapurapu
0086aa8f64 Added ref to documentation links on Basic dashboard help card (#1219)
* Created help Box guiding user to Prometheus documentation

* Created PrometheusIcon for help card

* Added ref to documentation links

* Changed order of url parameters

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-11 12:30:16 -08:00
Daniel Valdivia
abd9768bd9 Recover Icon. Add Tooltip support for TableActionButton (#1215)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-10 22:38:18 -08:00
jinapurapu
0e778a7466 Created Help Box on Basic Dashboard guiding user to Prometheus documentation (#1214)
* Created help Box guiding user to Prometheus documentation

* Created PrometheusIcon for help card

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-10 16:56:29 -08:00
Daniel Valdivia
fae0135f69 Fix Manage Tenant is disabled always in Tenant Summary (#1211)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2021-11-10 16:00:59 -08:00
Daniel Valdivia
3b69d9809e Match Checkbox Design (#1216)
* Match Checkbox Design

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

* unselected shadow box

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-10 15:25:05 -08:00
Harshavardhana
09a5dfebbc use container services in integration tests (#1213) 2021-11-10 12:10:29 -08:00
Lenin Alevski
9a01922c67 fix session duration regression (#1212)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-10 10:26:27 -08:00
Alex
6df6d785d7 Changed link button component for MinIO Image (#1208)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-10 09:54:22 -08:00
Lenin Alevski
e82103c678 Remove yarn warnings from portal-ui (#1207)
Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-10 09:47:47 -08:00
Lenin Alevski
c2f0889ff8 STS session token and console session cookie have same duration (#1202)
- `CONSOLE_STS_DURATION_IN_SECONDS` env renamed to `CONSOLE_STS_DURATION` to support more time formats

Signed-off-by: Lenin Alevski <alevsk.8772@gmail.com>
2021-11-09 21:41:00 -08:00
adfost
4a8ec219cc don't restart after every commit (#1204)
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2021-11-09 11:32:23 -08:00
Daniel Valdivia
e461a2268a Remove Warnings (#1200)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2021-11-08 22:43:00 -08:00
797 changed files with 151435 additions and 16616 deletions

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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/...)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
View File

@@ -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
View File

@@ -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=

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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"`

View 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
}

View File

@@ -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
View 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
}

View 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
}

View File

@@ -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]

View 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
}

View File

@@ -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
}

View File

@@ -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": {

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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
}
}
}

View File

@@ -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()
}

View File

@@ -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)
}

View File

@@ -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.

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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)
}

View File

@@ -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,
)

View File

@@ -1,3 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*

View File

@@ -1,3 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*

View File

@@ -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()

View File

@@ -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)

View File

@@ -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"
)

View File

@@ -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

View 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
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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"
)

View File

@@ -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

View 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 */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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

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

Some files were not shown because too many files have changed in this diff Show More