Compare commits

...

122 Commits

Author SHA1 Message Date
Daniel Valdivia
d027b7f759 Release v1.4.1 (#3360)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2024-05-24 12:35:06 -07:00
Aditya Manthramurthy
f1524b0120 Bump up minio/pkg to v3 (#3349) 2024-05-24 10:44:55 -07:00
Kaan Kabalak
9985892751 Update default issue message note (#3358) 2024-05-22 23:16:05 -07:00
Ramon de Klein
cfd60bdd91 Upgrade to Yarn 4 and fix vulnerability check (#3353) 2024-05-22 18:19:32 -07:00
Shireesh Anjal
779f2a86e5 Fix empty version in health report download (#3341) 2024-05-17 14:42:39 -06:00
Pedro Juarez
f47c4445bd Return header with error idp logout (#3346) 2024-05-12 09:30:46 -07:00
Kaan Kabalak
1aeb4cc3d5 Fix SUBNET capitalization in issue template (#3345) 2024-05-10 17:47:38 -06:00
Alex
9e0a0205cc Updated react-pdf dependency (#3342) 2024-05-10 09:11:09 -06:00
Harshavardhana
1058efb17a Remove all unnecessary Dockerfiles from repo (#3340) 2024-05-08 21:53:47 -06:00
Anis Eleuch
d0f744ebef svc: Assume access key creation permission to be available by default (#3306)
Allow SVC creation when CreateServiceAccount is denied with a condition

Adding this policy will make the user not able to create a service account anymore:

```
    {
      "Effect": "Deny",
      "Action": [
              "admin:CreateServiceAccount"
      ],
      "Condition": {
              "NumericGreaterThanIfExists": {"svc:DurationSeconds": "1500"}
      }
    },

```

The reason is that policy.IsAllowedActions() is called with conditions from the user login.

Assume svc account creation to be possible for now until we come up with a better fix

Co-authored-by: Anis Eleuch <anis@min.io>
Co-authored-by: Prakash Senthil Vel <23444145+prakashsvmx@users.noreply.github.com>
2024-05-08 09:47:57 -07:00
Cesar N
a8c043cb16 Use redirect URL in share link if env variable set (#3334) 2024-05-08 09:46:41 -07:00
dependabot[bot]
978e02b5dc Bump react-pdf from 7.7.1 to 7.7.3 in /web-app (#3337)
Bumps [react-pdf](https://github.com/wojtekmaj/react-pdf/tree/HEAD/packages/react-pdf) from 7.7.1 to 7.7.3.
- [Release notes](https://github.com/wojtekmaj/react-pdf/releases)
- [Commits](https://github.com/wojtekmaj/react-pdf/commits/v7.7.3/packages/react-pdf)

---
updated-dependencies:
- dependency-name: react-pdf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-08 09:46:13 -07:00
dependabot[bot]
b39dbfff96 Bump pdfjs-dist from 3.11.174 to 4.2.67 in /web-app (#3335)
Bumps [pdfjs-dist](https://github.com/mozilla/pdfjs-dist) from 3.11.174 to 4.2.67.
- [Commits](https://github.com/mozilla/pdfjs-dist/commits)

---
updated-dependencies:
- dependency-name: pdfjs-dist
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-08 09:46:03 -07:00
Alex
bd89cfde79 Release v1.4.0 (#3333) 2024-05-06 17:58:31 -06:00
Anis Eleuch
0bd563b2e5 Fix a leak in WS object browser (#3325)
```
goroutine 7399330769 [chan send, 70126 minutes]:
github.com/minio/console/api.(*wsMinioClient).objectManager.func2.1()
        github.com/minio/console@v0.46.0/api/ws_objects.go:135 +0x6f0
created by github.com/minio/console/api.(*wsMinioClient).objectManager.func2 in goroutine 7354918912
        github.com/minio/console@v0.46.0/api/ws_objects.go:95 +0x45e
```
2024-05-06 15:12:31 -07:00
Alex
22fe915629 Changed default Replicate Existing Objects behavior in MinIO UI (#3271)
Changed default Replicate Existing Objects behavior in UI

- Fixed replicate existing objects configuration saving
- Displayed full error message if error case ocurrs.
- Changed wording for this feature & enabled by default this setting

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-05-06 16:02:27 -06:00
Alex
aa161a5365 Added VersionID support to Metadata Details (#3332)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-05-06 14:38:53 -07:00
kcao
0557514cb4 fix: correct metric endpoint from minio_cluster_drive_free_inodes (#3296)
Fixes minio/console#3295
2024-05-06 03:56:08 -07:00
Alex
298203253c Updated UI dependencies (#3329)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-05-03 17:32:11 -06:00
Cesar N
cbeef2b248 Fix URL safe string decoding for DownloadPublicObject API (#3328)
Co-authored-by: cesnietor <cesar.nieto@min.io>
2024-05-03 15:33:46 -07:00
Harshavardhana
e68a74ba48 fix: passing correct httpClient, do not use DefaultClients (#3319)
most of our deployments use custom certificates, using DefaultClient
makes it virtually impossible to make share URL feature work.

this PR fixes this behavior in the implementation.

Bonus: re-use transports inside console, will add more changes to
take custom transport inputs in subsequent PR.
2024-05-01 09:46:35 -07:00
Ramon de Klein
02a0db1408 Use React hook to better deal with websockets (#3299) 2024-05-01 03:42:49 -07:00
dependabot[bot]
348376c672 Bump ejs from 3.1.9 to 3.1.10 in /web-app (#3324)
Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-01 02:53:56 -07:00
Kaan Kabalak
037b02e268 Make permission tests compatible with minio-js v8 (#3323)
Fixes #3322
2024-05-01 02:45:09 -07:00
Kaan Kabalak
fe534ab4e6 Temporarily fix permission tests failing due to minio-js version bump (#3321)
Fix permission tests failing due to minio-js version bump

Permission tests were failing due to function signature changes
introduced with the latest minio-js release. This is a temporary
measure until a Console PR to update test files is sent.
2024-04-30 14:32:02 -06:00
Cesar N
6625d54d67 Release v1.3.0 (#3313) 2024-04-24 18:15:13 -07:00
Cesar N
ee6d1ed586 Upgrade superagent package to fix vulnerability (#3314) 2024-04-24 17:27:42 -07:00
Cesar N
6de1d88e11 Use url-safe base64 encoding for download-shared-object api (#3305) 2024-04-23 08:36:30 -07:00
jinapurapu
de19b6f17b Make prefix field optional for adding tier (#3301) 2024-04-18 23:51:13 -06:00
jinapurapu
226a90be1d Adds ExpireDeleteMarker status to bucketLifecycleRule UI display (#3302) 2024-04-18 18:36:00 -06:00
Prakash Senthil Vel
6cfb6ff06a add user agent in admin client to display console in audit logs (#3297) 2024-04-17 10:49:15 -06:00
Alex
649c3d74b8 Release v1.2.0 (#3292)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-04-10 13:06:18 -06:00
Alex
662ce3b2f5 Update console dependencies to fix vulnerabilities (#3291)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-04-10 11:52:15 -06:00
dependabot[bot]
0292bc154d Bump express from 4.18.3 to 4.19.2 in /web-app (#3277)
Bumps [express](https://github.com/expressjs/express) from 4.18.3 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.3...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2024-04-10 11:40:56 -06:00
Cesar N
ceee83f03a Use Console as proxy for share object logic (#3284) 2024-04-10 11:16:17 -06:00
Prakash Senthil Vel
144904f0f6 fix ux for keys permissions (#3280) 2024-04-05 10:14:29 -07:00
Alex
963c8f1221 Added missing permissions validation to rewind button (#3282)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-04-04 23:41:20 -06:00
Shireesh Anjal
6c50c38f83 fix health report upload error (#3275) 2024-04-04 13:50:22 -06:00
Shireesh Anjal
3aac62cc81 Reuse GetClusterRegInfo from mc (#3270) 2024-04-01 09:14:54 -07:00
Cesar N
78a05d39c4 Log error if it exists while serving APIs (#3276)
Co-authored-by: cesnietor <>
2024-03-27 13:06:42 -07:00
dependabot[bot]
79bec3880e Bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /web-app (#3273) 2024-03-24 05:39:34 +01:00
Alex
bdf7bd6309 Changed Bucket Access Policy default value from n/a to private (#3267)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-03-19 18:28:18 -06:00
dependabot[bot]
4ce1ba999b Bump follow-redirects from 1.15.5 to 1.15.6 in /web-app (#3266) 2024-03-14 21:05:39 -06:00
Alex
d01501703b Release v1.1.1 (#3265)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-03-14 16:34:57 -07:00
Cesar N
6a38a09462 Fix folder download (#3264) 2024-03-14 15:07:15 -06:00
Alex
78990e354f Release v1.1.0 (#3261)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-03-12 11:22:55 -06:00
Harshavardhana
3189ebdfef Update all go-deps (#3259) 2024-03-12 01:47:35 -06:00
Shubhendu
39bf627b0a Enable console to set expired-object-all-versions (#3226)
Signed-off-by: Shubhendu Ram Tripathi <shubhendu@minio.io>
2024-03-11 14:25:06 -06:00
Alex
a838c763ea Release v1.0.0 (#3252)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-02-29 13:45:03 -08:00
Aditya Manthramurthy
0afea63994 Fix: handling of no inline policy for service acc. (#3221) 2024-02-29 14:51:12 -06:00
Phillip Schichtel
0df9487527 Check the blob size instead of the progress reports (#3249) 2024-02-29 08:33:26 -08:00
Victor Bayas
9274ee72ad Fix URL of inspect object API (#3247) 2024-02-28 20:51:09 -06:00
Prakash Senthil Vel
2b6c3debb4 clean up text preview support which was removed earlier (#3251) 2024-02-28 09:00:41 -08:00
Victor Bayas
8dd6dd4e7f Use native WebSocket API (#3248) 2024-02-27 13:34:06 -08:00
dependabot[bot]
5e64c96497 Bump ip from 1.1.8 to 1.1.9 in /web-app (#3241)
Bumps [ip](https://github.com/indutny/node-ip) from 1.1.8 to 1.1.9.
- [Commits](https://github.com/indutny/node-ip/compare/v1.1.8...v1.1.9)

---
updated-dependencies:
- dependency-name: ip
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
2024-02-26 13:45:16 -08:00
jinapurapu
54c0b4b8a2 Add bucket replication screen (#3040) 2024-02-26 13:44:55 -08:00
Prakash Senthil Vel
31056e12ba No preview message UI (#3244) 2024-02-26 11:34:21 -06:00
Alex
151c8117a3 Release v0.46.0 (#3238) 2024-02-16 13:58:01 -08:00
Alex
9b5c17c2db Updated failing UI tests in console (#3236)
Updated failing tests in console

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-02-14 17:48:41 -06:00
Alex
23e01b257e Updated mds to v0.18.1 (#3233)
- Updated other project dependencies
- Fixed an issue while pressing enter key in a page that contains a select box
- Fixed an issue while selecting an autocomplete option from an input box

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-02-13 17:53:11 -06:00
jinapurapu
ecc8c7a86e Added latest blog content to help menu (#3223) 2024-02-13 00:28:05 -08:00
Harshavardhana
ee4d7b9b69 upgrade all dependencies for console (#3235)
Signed-off-by: Harshavardhana <harsha@minio.io>
2024-02-12 22:17:21 -08:00
Alex
80c03839a4 Fixed lint issues with files (#3234)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-02-12 21:55:17 -08:00
jinapurapu
f394cb69ce Fixed disabled Create User button if policy has no resource (#3231)
Co-authored-by: Jillian Inapurapu <jillii@Jillians-MBP.attlocal.net>
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2024-02-12 09:54:32 -08:00
Prakash Senthil Vel
52137ba9e5 Logout state clean up (#3219) 2024-02-09 15:36:56 -06:00
Prakash Senthil Vel
942b8101cc Fix lifecycle rule and edit modal to be consistent to display tier (#3227) 2024-02-07 11:35:25 -06:00
jinapurapu
a0a6b33ecd Add HelpTip to clarify Usage calculation (#3143) 2024-01-30 23:15:11 -06:00
Cesar N
d4c5e1b51c Fail request when error occurs during download (#3214) 2024-01-26 15:06:25 -06:00
jinapurapu
96923aed75 Changed DeleteAccessRule to use swagger api (#3213) 2024-01-26 14:59:34 -06:00
Shubhendu
a04f833e3f Query params replicate-ilm-expiry and disable-ilm-expiry-replication (#3065)
Signed-off-by: Shubhendu Ram Tripathi <shubhendu@minio.io>
2024-01-26 14:59:09 -06:00
dependabot[bot]
3b52cc9bd4 Bump github.com/lestrrat-go/jwx from 1.2.27 to 1.2.28 (#3215)
Bumps [github.com/lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) from 1.2.27 to 1.2.28.
- [Release notes](https://github.com/lestrrat-go/jwx/releases)
- [Changelog](https://github.com/lestrrat-go/jwx/blob/v1.2.28/Changes)
- [Commits](https://github.com/lestrrat-go/jwx/compare/v1.2.27...v1.2.28)

---
updated-dependencies:
- dependency-name: github.com/lestrrat-go/jwx
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-26 12:01:41 -06:00
Cesar N
df2e92e451 Use swagger api for Site Replication Status (#3208) 2024-01-24 23:05:27 -06:00
Cesar N
8836fe043b Return proper progress on download error (#3211) 2024-01-23 10:55:41 -06:00
Cesar N
7ce6a58099 Use swagger api for Get API from Subnet (#3207) 2024-01-22 10:42:33 -06:00
Haruaki
57d6aca716 Fix BucketNamingRules button click (#3209) 2024-01-22 10:41:35 -06:00
Cesar N
8d99637455 Use swagger api for Add KMS key in Bucket Encryption (#3205) 2024-01-21 22:16:10 -08:00
Cesar N
abd66780f4 Use swagger api for AirGap Subnet Registration (#3206) 2024-01-19 14:17:23 -06:00
Cesar N
a5175a35ec Use swagger api for import KSM Key (#3204) 2024-01-19 11:07:05 -08:00
Cesar N
d9f945b5df Use swagger api for Add KMS Key (#3202) 2024-01-18 22:41:40 -08:00
Cesar N
0c55e39e8c Use swagger api for Add IDP Configuration (#3201) 2024-01-18 16:03:01 -08:00
Cesar N
b5443952da Use swagger api for IDP configuration details (#3200) 2024-01-18 15:02:11 -08:00
Cesar N
b9f0ccfaba Use swagger api for delete single and multiple Service Accounts (#3199) 2024-01-18 11:55:56 -05:00
Daniel Valdivia
24742325b7 Remove useAPI from DeleteUser and DeleteIDPConfigurationModal (#3191) 2024-01-17 15:37:28 -08:00
Cesar N
c87ebe447f Use swagger api for delete KMS key (#3197) 2024-01-17 15:31:19 -06:00
Cesar N
462cf16db9 Use swagger api for delete Policy (#3198) 2024-01-17 12:06:03 -08:00
Cesar N
edaa4e8754 Use swagger api for delete group (#3196) 2024-01-17 11:49:03 -08:00
Cesar N
76c596c574 Disable KMS Endpoints and Metrics Tabs if using KMS Secret Key (#3193) 2024-01-17 09:05:10 -08:00
Alex
b5554f6dcf Added Dark / Light Mode Status icons (#3194)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-01-16 19:06:58 -06:00
Daniel Valdivia
fc65f1afd1 Add Base URI to Inspect API calls (#3190)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2024-01-16 13:45:27 -08:00
Cesar N
b066b6a920 Kms status endpoints null validation (#3189) 2024-01-12 16:32:37 -06:00
Alex
bc0e63aac8 Release v0.45.0 (#3187)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-01-10 21:48:08 -08:00
Alex
343ff575e6 Removed heal backend (#3188)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-01-10 21:16:08 -08:00
Alex
08c922dca6 Deprecated Heal (Drives) functionality (#3186)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-01-10 22:33:18 -06:00
Alex
4dd6519cc6 Updated Section titles & labels (#3185)
Renamed Subscription to Subnet in menus
Renamed Settings to Configuration
Renamed Diagnostics to Heath

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2024-01-10 22:16:24 -06:00
Prakash Senthil Vel
cdffdae289 Fix life cycle rule edit for transition (#3183) 2024-01-08 08:43:07 -06:00
Shireesh Anjal
27e3b82223 Use subnet package in pkg for license validation (#3156) 2023-12-29 12:12:27 -06:00
Daniel Valdivia
239b31748a Rename portal-ui to web-app (#3178)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-29 11:44:01 -06:00
Daniel Valdivia
b465b74326 Release v0.44.0 (#3177)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-27 00:11:15 -08:00
Daniel Valdivia
616f262d09 Rename restapi to api (#3176)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-26 15:07:30 -06:00
Harshavardhana
8aa0ec17c5 simplify the provider config init, loading and allow reachable IDPs (#3168)
fixes https://github.com/minio/console/issues/3018
2023-12-26 14:38:42 -06:00
Daniel Valdivia
a8c5b53a2c Pkg Subnet Utils Tests (#3173)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-26 14:29:11 -06:00
Cesar Celis Hernandez
e96dbd444e Add all possible tests under restapi (#3174) 2023-12-26 14:17:40 -06:00
Prakash Senthil Vel
939e2acb0b fix event dest icons not loading when subpath is configured (#3169)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-26 14:03:25 -06:00
Daniel Valdivia
a04955dc70 Save all coverage files to play (#3170)
* Save all coverage files to play

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

* Save them to latest as well

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

---------

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-26 13:52:18 -06:00
Cesar Celis Hernandez
ba04a22492 Adjusting the threshold of the coverage (#3172) 2023-12-26 13:52:03 -06:00
Cesar Celis Hernandez
a281fe129f To include pkg tests in the coverage (#3171)
Execute and include pkg tests in the coverage
2023-12-26 13:34:25 -06:00
Daniel Valdivia
a655cc8d3b Upgrade Go Dependencies (#3167) 2023-12-23 08:26:57 -06:00
Daniel Valdivia
63b584c83d Change Loading Logic for Metrics Page (#3166)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-22 10:25:54 -06:00
Alex
7dffd5f079 Release v0.43.1 (#3161) 2023-12-18 17:00:58 -06:00
Cesar N
044e5702df Update Share Object UI to reflect max expiration time (#3098) 2023-12-14 15:28:11 -06:00
Alex
3c3b9546d9 Release v0.43.0 (#3159)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-12 21:53:25 -06:00
jinapurapu
5bc0e74b53 Omit detailedMessage from login errors (#3136) 2023-12-12 18:09:56 -06:00
Alex
f0d4dddacd Changed PDF file preview behavior (#3144)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-12 14:20:06 -06:00
Prakash Senthil Vel
f4a3f46bcf Fix to prevent extra metadata call when listing at a bucket level (#3158) 2023-12-12 10:56:48 -06:00
Alex
38472e4cd2 Updated Console dependencies (#3157)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-11 18:29:07 -06:00
Daniel Valdivia
9db5d1e4f4 Tests for pkg/utils (#3155)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-11 09:57:02 -08:00
jinapurapu
4cadaf7d49 Cleaned up Tooltips and HelpTips on AddBucket screen (#3154) 2023-12-11 11:33:28 -06:00
Adrian Najera
748486160f FIX: Use STS env variable to increase the IDP token expiration (#3132)
Share link duration is based on the token expiration,
this increases the IDP token expiration so the share link
is able to last longer, by using an env variable called
MINIO_STS_DURATION
2023-12-08 09:58:46 -08:00
Alex
2c0a0b2bc4 Release v0.42.2 (#3153)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-07 15:37:44 -06:00
Daniel Valdivia
7e51d4bebb Don't attempt to show prometheus metrics if URL is empty (#3152)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
2023-12-07 15:16:03 -06:00
Alex
c011e67122 Release v0.42.1 (#3150)
Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-06 19:10:28 -06:00
Alex
394b4c403d Rollback to go 1.19 (#3149)
Rollback go version to go 1.19, This is a requirement of MinIO server

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
2023-12-06 16:55:03 -08:00
1813 changed files with 151108 additions and 19941 deletions

View File

@@ -1,7 +0,0 @@
node_modules/
dist/
target/
console
!console/
portal-ui/node_modules/
.git/

View File

@@ -8,7 +8,8 @@ assignees: ''
---
## NOTE
If this case is urgent, please subscribe to [Subnet](https://min.io/pricing) so that our 24/7 support team may help you faster.
Please subscribe to our [paid subscription plans](https://min.io/pricing) for 24x7 support from our Engineering team.
<!--- Provide a general summary of the issue in the title above -->

View File

@@ -1,166 +0,0 @@
# @format
name: Cross Compile
on:
pull_request:
branches:
- master
paths:
- go.sum
# 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:
cross-compile-1:
name: Cross compile
needs:
- lint-job
- ui-assets
- reuse-golang-dependencies
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.21.x ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
cache: true
id: go
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make crosscompile arg1="'linux/ppc64le linux/mips64'"
cross-compile-2:
name: Cross compile 2
needs:
- lint-job
- ui-assets
- reuse-golang-dependencies
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.21.x ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
cache: true
id: go
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make crosscompile arg1="'linux/arm64 linux/s390x'"
cross-compile-3:
name: Cross compile 3
needs:
- lint-job
- ui-assets
- reuse-golang-dependencies
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.21.x ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
cache: true
id: go
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make crosscompile arg1="'darwin/amd64 freebsd/amd64'"
cross-compile-4:
name: Cross compile 4
needs:
- lint-job
- ui-assets
- reuse-golang-dependencies
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.21.x ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
cache: true
id: go
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make crosscompile arg1="'windows/amd64 linux/arm'"
cross-compile-5:
name: Cross compile 5
needs:
- lint-job
- ui-assets
- reuse-golang-dependencies
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.21.x ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
cache: true
id: go
- name: Build on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make crosscompile arg1="'linux/386 netbsd/amd64'"

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.21.5
go-version: 1.22.3
check-latest: true
- name: Get official govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest
@@ -36,18 +36,28 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ 1.21.5 ]
go-version: [ 1.22.3 ]
os: [ ubuntu-latest ]
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Read .nvmrc
id: node_version
run: echo "$(cat .nvmrc)" && echo "NVMRC=$(cat .nvmrc)" >> $GITHUB_ENV
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@v3
with:
node-version: ${{ env.NVMRC }}
cache: "yarn"
cache-dependency-path: portal-ui/yarn.lock
- name: Checks for known security issues with the installed packages
working-directory: ./portal-ui
working-directory: ./web-app
continue-on-error: false
run: |
yarn audit --groups dependencies
# Ignore "pdfjs-dist" advisory, because it's a dependency
# of "react-pdf" that cannot be upgraded. Because the
# "isEvalSupported" value is always set to "false", it
# isn't a security problem. See also
# - https://github.com/wojtekmaj/react-pdf/issues/1789
# - https://github.com/wojtekmaj/react-pdf/discussions/1786
# - https://www.npmjs.com/advisories/1097244
yarn npm audit --recursive --environment production --no-deprecations --ignore 1097244

10
.gitignore vendored
View File

@@ -1,12 +1,12 @@
# Playwright Data
portal-ui/storage/
portal-ui/playwright/.auth/admin.json
web-app/storage/
web-app/playwright/.auth/admin.json
# Report from Playwright
portal-ui/playwright-report/
web-app/playwright-report/
# Coverage from Playwright
portal-ui/.nyc_output/
web-app/.nyc_output/
# Binaries for programs and plugins
*.exe
@@ -37,7 +37,7 @@ dist/
# Ignore node_modules
portal-ui/node_modules/
web-app/node_modules/
# Ignore tls cert and key
private.key

View File

@@ -46,4 +46,4 @@ run:
skip-dirs:
- pkg/clientgen
- pkg/apis/networking.gke.io
- restapi/operations
- api/operations

View File

@@ -5,7 +5,7 @@
# Common large paths
node_modules/
portal-ui/node_modules/
web-app/node_modules/
build/
dist/
.idea/

View File

@@ -2,6 +2,137 @@
# Changelog
## Release v1.4.0
Features:
- Added VersionID support to metadata details
- Improved Websockets handlers
Bug Fix:
- Fixed vulnerabilities and updated dependencies
- Fixed an issue with Download URL decoding
- Fixed leak in Object Browser Websocket
- Minor UX fixes
## Release v1.3.0
Features:
- Adds ExpireDeleteMarker status to BucketLifecycleRule UI
Bug Fix:
- Fixed vulnerability
- Used URL-safe base64 enconding for Share API
- Made Prefix field optional when Adding Tier
- Added Console user agent in MinIO Admin Client
## Release v1.2.0
Features:
- Updated file share logic to work as Proxy
Bug Fix:
- Updated project dependencies
- Fixed Key Permissions UX
- Added permissions validation to rewind button
- Fixed Health report upload to SUBNET
- Misc Cosmetic fixes
## Release v1.1.1
Bug Fix:
- Fixed folder download issue
## Release v1.1.0
Features:
- Added Set Expired object all versions selector
Bug Fix:
- Updated Go Dependencies
## Release v1.0.0
Features:
- Updated Preview message alert
Bug Fix:
- Updated Websocket API
- Fixed issues with download manager
- Fixed policies issues
## Release v0.46.0
Features:
- Added latest help content to forms
Bug Fix:
- Disabled Create User button in certain policy cases
- Fixed an issue with Logout request
- Upgraded project dependencies
## Release v0.45.0
Deprecated:
- Deprecated Heal / Drives page
Features:
- Updated tines on menus & pages
Bug Fix:
- Upgraded project dependencies
## Release v0.44.0
Bug Fix:
- Upgraded project dependencies
- Fixed events icons not loading in subpaths
## Release v0.43.1
Bug Fix:
- Update Share Object UI to reflect maximum expiration time in UI
## Release v0.43.0
Features:
- Updated PDF preview method
Bug Fix:
- Fixed vulnerabilities
- Prevented non-necessary metadata calls in object browser
## Release v0.42.2
Bug Fix:
- Hidden Prometheus metrics if URL is empty
## Release v0.42.1
Bug Fix:
- Reset go version to 1.19
## Release v0.42.0
Features:

View File

@@ -4,56 +4,80 @@ This is a REST portal server created using [go-swagger](https://github.com/go-sw
The API handlers are created using a YAML definition located in `swagger.YAML`.
To add new api, the YAML file needs to be updated with all the desired apis using the [Swagger Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/), this includes paths, parameters, definitions, tags, etc.
To add new api, the YAML file needs to be updated with all the desired apis using
the [Swagger Basic Structure](https://swagger.io/docs/specification/2-0/basic-structure/), this includes paths,
parameters, definitions, tags, etc.
## Generate server from YAML
Once the YAML file is ready we can autogenerate the code needed for the new api by just running:
Validate it:
```
swagger validate ./swagger.yml
```
Update server code:
```
make swagger-gen
```
This will update all the necessary code.
`./restapi/configure_console.go` is a file that contains the handlers to be used by the application, here is the only place where we need to update our code to support the new apis. This file is not affected when running the swagger generator and it is safe to edit.
`./api/configure_console.go` is a file that contains the handlers to be used by the application, here is the only place
where we need to update our code to support the new apis. This file is not affected when running the swagger generator
and it is safe to edit.
## Unit Tests
`./restapi/handlers_test.go` needs to be updated with the proper tests for the new api.
`./api/handlers_test.go` needs to be updated with the proper tests for the new api.
To run tests:
```
go test ./restapi
go test ./api
```
## Commit changes
After verification, commit your changes. This is a [great post](https://chris.beams.io/posts/git-commit/) on how to write useful commit messages
After verification, commit your changes. This is a [great post](https://chris.beams.io/posts/git-commit/) on how to
write useful commit messages
```
$ git commit -am 'Add some feature'
```
### Push to the branch
Push your locally committed changes to the remote origin (your fork)
```
$ git push origin my-new-feature
```
### Create a Pull Request
Pull requests can be created via GitHub. Refer to [this document](https://help.github.com/articles/creating-a-pull-request/) for detailed steps on how to create a pull request. After a Pull Request gets peer reviewed and approved, it will be merged.
Pull requests can be created via GitHub. Refer
to [this document](https://help.github.com/articles/creating-a-pull-request/) for detailed steps on how to create a pull
request. After a Pull Request gets peer reviewed and approved, it will be merged.
## FAQs
### How does ``console`` manages dependencies?
``MinIO`` uses `go mod` to manage its dependencies.
- Run `go get foo/bar` in the source folder to add the dependency to `go.mod` file.
To remove a dependency
- Edit your code and remove the import reference.
- Run `go mod tidy` in the source folder to remove dependency from `go.mod` file.
### What are the coding guidelines for console?
``console`` is fully conformant with Golang style. Refer: [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments) article from Golang project. If you observe offending code, please feel free to send a pull request or ping us on [Slack](https://slack.min.io).
``console`` is fully conformant with Golang style.
Refer: [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments) article from Golang project. If you observe
offending code, please feel free to send a pull request or ping us on [Slack](https://slack.min.io).

2345
CREDITS

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,20 @@
# Developing MinIO Console
The MinIO Console requires the [MinIO Server](https://github.com/minio/minio). For development purposes, you also need to run both the MinIO Console web app and the MinIO Console server.
The MinIO Console requires the [MinIO Server](https://github.com/minio/minio). For development purposes, you also need
to run both the MinIO Console web app and the MinIO Console server.
## Running MinIO Console server
Build the server in the main folder by running:
```
make
```
> Note: If it's the first time running the server, you might need to run `go mod tidy` to ensure you have all modules required.
To start the server run:
> Note: If it's the first time running the server, you might need to run `go mod tidy` to ensure you have all modules
> required.
> To start the server run:
```
CONSOLE_ACCESS_KEY=<your-access-key>
CONSOLE_SECRET_KEY=<your-secret-key>
@@ -19,8 +24,8 @@ CONSOLE_DEV_MODE=on
```
## Running MinIO Console web app
Refer to `/portal-ui` [instructions](/portal-ui/README.md) to run the web app locally.
Refer to `/web-app` [instructions](/web-app/README.md) to run the web app locally.
# Building with MinIO
@@ -72,25 +77,6 @@ Still in the MinIO folder, run
make build
```
# Testing on Kubernetes
If you want to test console on kubernetes, you can perform all the steps from `Building with MinIO`, but change `Step 3`
to the following:
```shell
TAG=miniodev/console:dev make docker
```
This will build a docker container image that can be used to test with your local kubernetes environment.
For example, if you are using kind:
```shell
kind load docker-image miniodev/console:dev
```
and then deploy any `Tenant` that uses this image
# LDAP authentication with Console
## Setup

View File

@@ -1,43 +0,0 @@
ARG NODE_VERSION
FROM node:$NODE_VERSION as uilayer
WORKDIR /app
COPY ./portal-ui/package.json ./
COPY ./portal-ui/yarn.lock ./
RUN yarn install
COPY ./portal-ui .
RUN make build-static
USER node
FROM golang:1.19 as golayer
RUN apt-get update -y && apt-get install -y ca-certificates
ADD go.mod /go/src/github.com/minio/console/go.mod
ADD go.sum /go/src/github.com/minio/console/go.sum
WORKDIR /go/src/github.com/minio/console/
# Get dependencies - will also be cached if we won't change mod/sum
RUN go mod download
ADD . /go/src/github.com/minio/console/
WORKDIR /go/src/github.com/minio/console/
ENV CGO_ENABLED=0
COPY --from=uilayer /app/build /go/src/github.com/minio/console/portal-ui/build
RUN go build --tags=kqueue,operator -ldflags "-w -s" -a -o console ./cmd/console
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.7
MAINTAINER MinIO Development "dev@min.io"
EXPOSE 9090
COPY --from=golayer /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=golayer /go/src/github.com/minio/console/console .
ENTRYPOINT ["/console"]

View File

@@ -1,14 +0,0 @@
ARG NODE_VERSION
FROM node:$NODE_VERSION as uilayer
WORKDIR /app
COPY ./portal-ui/package.json ./
COPY ./portal-ui/yarn.lock ./
RUN yarn install
COPY ./portal-ui .
RUN yarn install && make build-static
USER node

View File

@@ -1,27 +0,0 @@
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.2 as build
RUN microdnf update --nodocs && microdnf install ca-certificates --nodocs
FROM registry.access.redhat.com/ubi9/ubi-micro:9.2
ARG TAG
LABEL name="MinIO" \
vendor="MinIO Inc <dev@min.io>" \
maintainer="MinIO Inc <dev@min.io>" \
version="${TAG}" \
release="${TAG}" \
summary="A graphical user interface for MinIO" \
description="MinIO object storage is fundamentally different. Designed for performance and the S3 API, it is 100% open-source. MinIO is ideal for large, private cloud environments with stringent security requirements and delivers mission-critical availability across a diverse range of workloads."
# On RHEL the certificate bundle is located at:
# - /etc/pki/tls/certs/ca-bundle.crt (RHEL 6)
# - /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (RHEL 7)
COPY --from=build /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem /etc/pki/ca-trust/extracted/pem/
COPY LICENSE /LICENSE
COPY CREDITS /CREDITS
COPY console /console
EXPOSE 9090
ENTRYPOINT ["/console"]

View File

@@ -33,6 +33,10 @@ lint:
@GO111MODULE=on ${GOPATH}/bin/golangci-lint cache clean
@GO111MODULE=on ${GOPATH}/bin/golangci-lint run --timeout=5m --config ./.golangci.yml
lint-fix: getdeps ## runs golangci-lint suite of linters with automatic fixes
@echo "Running $@ check"
@GO111MODULE=on ${GOPATH}/bin/golangci-lint run --timeout=5m --config ./.golangci.yml --fix
install: console
@echo "Installing console binary to '$(GOPATH)/bin/console'"
@mkdir -p $(GOPATH)/bin && cp -f $(PWD)/console $(GOPATH)/bin/console
@@ -48,19 +52,19 @@ apply-gofmt:
clean-swagger:
@echo "cleaning"
@rm -rf models
@rm -rf restapi/operations
@rm -rf api/operations
swagger-console:
@echo "Generating swagger server code from yaml"
@swagger generate server -A console --main-package=management --server-package=restapi --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
@swagger generate server -A console --main-package=management --server-package=api --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
@echo "Generating typescript api"
@npx swagger-typescript-api -p ./swagger.yml -o ./portal-ui/src/api -n consoleApi.ts
@git restore restapi/server.go
@npx swagger-typescript-api -p ./swagger.yml -o ./web-app/src/api -n consoleApi.ts
@git restore api/server.go
assets:
@(if [ -f "${NVM_DIR}/nvm.sh" ]; then \. "${NVM_DIR}/nvm.sh" && nvm install && nvm use && npm install -g yarn ; fi &&\
cd portal-ui; yarn install --prefer-offline; make build-static; yarn prettier --write . --loglevel warn; cd ..)
cd web-app; corepack enable; yarn install --prefer-offline; make build-static; yarn prettier --write . --loglevel warn; cd ..)
test-integration:
@(docker stop pgsqlcontainer || true)
@@ -78,7 +82,7 @@ test-integration:
@echo "Postgres"
@(docker run --net=mynet123 --ip=173.18.0.4 --name pgsqlcontainer --rm -p 5432:5432 -e POSTGRES_PASSWORD=password -d postgres && sleep 5)
@echo "execute test and get coverage for test-integration:"
@(cd integration && go test -coverpkg=../restapi -c -tags testrunmain . && mkdir -p coverage && ./integration.test -test.v -test.run "^Test*" -test.coverprofile=coverage/system.out)
@(cd integration && go test -coverpkg=../api -c -tags testrunmain . && mkdir -p coverage && ./integration.test -test.v -test.run "^Test*" -test.coverprofile=coverage/system.out)
@(docker stop pgsqlcontainer)
@(docker stop minio)
@(docker stop minio2)
@@ -126,7 +130,7 @@ test-replication:
$(MINIO_VERSION) server /data{1...4} \
--address :9002 \
--console-address :6002)
@(cd replication && go test -coverpkg=../restapi -c -tags testrunmain . && mkdir -p coverage && ./replication.test -test.v -test.run "^Test*" -test.coverprofile=coverage/replication.out)
@(cd replication && go test -coverpkg=../api -c -tags testrunmain . && mkdir -p coverage && ./replication.test -test.v -test.run "^Test*" -test.coverprofile=coverage/replication.out)
@(docker stop minio || true)
@(docker stop minio1 || true)
@(docker stop minio2 || true)
@@ -180,45 +184,45 @@ test-sso-integration:
@echo "add python module"
@(pip3 install bs4)
@echo "Executing the test:"
@(cd sso-integration && go test -coverpkg=../restapi -c -tags testrunmain . && mkdir -p coverage && ./sso-integration.test -test.v -test.run "^Test*" -test.coverprofile=coverage/sso-system.out)
@(cd sso-integration && go test -coverpkg=../api -c -tags testrunmain . && mkdir -p coverage && ./sso-integration.test -test.v -test.run "^Test*" -test.coverprofile=coverage/sso-system.out)
test-permissions-1:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-1/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-1/")
@(docker stop minio)
test-permissions-2:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-2/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-2/")
@(docker stop minio)
test-permissions-3:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-3/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-3/")
@(docker stop minio)
test-permissions-4:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-4/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-4/")
@(docker stop minio)
test-permissions-5:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-5/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-5/")
@(docker stop minio)
test-permissions-6:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-6/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-6/")
@(docker stop minio)
test-permissions-7:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh "portal-ui/tests/permissions-7/")
@(env bash $(PWD)/web-app/tests/scripts/permissions.sh "web-app/tests/permissions-7/")
@(docker stop minio)
test-apply-permissions:
@(env bash $(PWD)/portal-ui/tests/scripts/initialize-env.sh)
@(env bash $(PWD)/web-app/tests/scripts/initialize-env.sh)
test-start-docker-minio:
@(docker run -v /data1 -v /data2 -v /data3 -v /data4 -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@@ -227,7 +231,7 @@ initialize-permissions: test-start-docker-minio test-apply-permissions
@echo "Done initializing permissions test"
cleanup-permissions:
@(env bash $(PWD)/portal-ui/tests/scripts/cleanup-env.sh)
@(env bash $(PWD)/web-app/tests/scripts/cleanup-env.sh)
@(docker stop minio)
initialize-docker-network:
@@ -246,7 +250,7 @@ test-start-docker-nginx-w-subpath:
--network host \
-d --rm \
--add-host=host.docker.internal:host-gateway \
-v ./portal-ui/tests/subpath-nginx/nginx.conf:/etc/nginx/nginx.conf \
-v ./web-app/tests/subpath-nginx/nginx.conf:/etc/nginx/nginx.conf \
--name test-nginx nginx)
test-initialize-minio-nginx: test-start-docker-minio-w-redirect-url test-start-docker-nginx-w-subpath
@@ -254,17 +258,23 @@ test-initialize-minio-nginx: test-start-docker-minio-w-redirect-url test-start-d
cleanup-minio-nginx:
@(docker stop minio test-nginx & docker network rm test-network)
# https://stackoverflow.com/questions/19200235/golang-tests-in-sub-directory
# Note: go test ./... will run tests on the current folder and all subfolders.
# This is needed because tests can be in the folder or sub-folder(s), let's include them all please!.
test:
@echo "execute test and get coverage"
@(cd restapi && mkdir coverage && GO111MODULE=on go test -test.v -coverprofile=coverage/coverage.out)
@(cd api && mkdir -p coverage && GO111MODULE=on go test ./... -test.v -coverprofile=coverage/coverage.out)
# https://stackoverflow.com/questions/19200235/golang-tests-in-sub-directory
# Note: go test ./... will run tests on the current folder and all subfolders.
# This is since tests in pkg folder are in subfolders and were not executed.
test-pkg:
@echo "execute test and get coverage"
@(cd pkg && mkdir coverage && GO111MODULE=on go test -test.v -coverprofile=coverage/coverage-pkg.out)
@(cd pkg && mkdir -p coverage && GO111MODULE=on go test ./... -test.v -coverprofile=coverage/coverage-pkg.out)
coverage:
@(GO111MODULE=on go test -v -coverprofile=coverage.out github.com/minio/console/restapi/... && go tool cover -html=coverage.out && open coverage.html)
@(GO111MODULE=on go test -v -coverprofile=coverage.out github.com/minio/console/api/... && go tool cover -html=coverage.out && open coverage.html)
clean:
@echo "Cleaning up all the generated files"
@@ -279,4 +289,4 @@ release: swagger-gen
@echo "Generating Release: $(RELEASE)"
@make assets
@git add -u .
@git add portal-ui/build/
@git add web-app/build/

View File

@@ -35,7 +35,7 @@ In case a Console standalone binary is needed, it can be generated by building t
### 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.19
> Minimum version required is go1.21
```
go install github.com/minio/console/cmd/console@latest

View File

@@ -14,16 +14,16 @@
// 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 restapi
package api
import (
"context"
systemApi "github.com/minio/console/restapi/operations/system"
systemApi "github.com/minio/console/api/operations/system"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
)
func registerAdminArnsHandlers(api *operations.ConsoleAPI) {

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -25,11 +25,11 @@ import (
"testing"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations/system"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations/system"
"github.com/go-openapi/loads"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/api/operations"
"github.com/minio/madmin-go/v3"
asrt "github.com/stretchr/testify/assert"
@@ -39,7 +39,7 @@ func TestArnsList(t *testing.T) {
assert := asrt.New(t)
adminClient := AdminClientMock{}
// Test-1 : getArns() returns proper arn list
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{
SQSARN: []string{"uno"},
}, nil
@@ -54,7 +54,7 @@ func TestArnsList(t *testing.T) {
assert.Nil(err, "Error should have been nil")
// Test-2 : getArns(ctx) fails for whatever reason
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{}, errors.New("some reason")
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -22,7 +22,7 @@ import (
"time"
"github.com/minio/madmin-go/v3"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
)
type AdminClientMock struct{}
@@ -47,7 +47,7 @@ var (
minioHealMock func(ctx context.Context, bucket, prefix string, healOpts madmin.HealOpts, clientToken string,
forceStart, forceStop bool) (healStart madmin.HealStartSuccess, healTaskStatus madmin.HealTaskStatus, err error)
minioServerHealthInfoMock func(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) (interface{}, string, error)
minioServerHealthInfoMock func(ctx context.Context, deadline time.Duration) (interface{}, string, error)
minioListPoliciesMock func() (map[string]*iampolicy.Policy, error)
minioGetPolicyMock func(name string) (*iampolicy.Policy, error)
@@ -80,7 +80,7 @@ var (
minioSetUserStatusMock func(accessKey string, status madmin.AccountStatus) error
minioAccountInfoMock func(ctx context.Context) (madmin.AccountInfo, error)
minioAddServiceAccountMock func(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string, description string, name string, expiry *time.Time, status string) (madmin.Credentials, error)
minioAddServiceAccountMock func(ctx context.Context, policy string, user string, accessKey string, secretKey string, description string, name string, expiry *time.Time, status string) (madmin.Credentials, error)
minioListServiceAccountsMock func(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error)
minioDeleteServiceAccountMock func(ctx context.Context, serviceAccount string) error
minioInfoServiceAccountMock func(ctx context.Context, serviceAccount string) (madmin.InfoServiceAccountResp, error)
@@ -174,8 +174,8 @@ func (ac AdminClientMock) heal(ctx context.Context, bucket, prefix string, healO
return minioHealMock(ctx, bucket, prefix, healOpts, clientToken, forceStart, forceStop)
}
func (ac AdminClientMock) serverHealthInfo(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) (interface{}, string, error) {
return minioServerHealthInfoMock(ctx, healthDataTypes, deadline)
func (ac AdminClientMock) serverHealthInfo(ctx context.Context, deadline time.Duration) (interface{}, string, error) {
return minioServerHealthInfoMock(ctx, deadline)
}
func (ac AdminClientMock) addOrUpdateIDPConfig(_ context.Context, _, _, _ string, _ bool) (restart bool, err error) {
@@ -317,11 +317,11 @@ func (ac AdminClientMock) getSiteReplicationInfo(ctx context.Context) (*madmin.S
return getSiteReplicationInfo(ctx)
}
func (ac AdminClientMock) addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite) (*madmin.ReplicateAddStatus, error) {
func (ac AdminClientMock) addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite, _ madmin.SRAddOptions) (*madmin.ReplicateAddStatus, error) {
return addSiteReplicationInfo(ctx, sites)
}
func (ac AdminClientMock) editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo) (*madmin.ReplicateEditStatus, error) {
func (ac AdminClientMock) editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo, _ madmin.SREditOptions) (*madmin.ReplicateEditStatus, error) {
return editSiteReplicationInfo(ctx, site)
}
@@ -377,7 +377,7 @@ func (ac AdminClientMock) AccountInfo(ctx context.Context) (madmin.AccountInfo,
return minioAccountInfoMock(ctx)
}
func (ac AdminClientMock) addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string, description string, name string, expiry *time.Time, status string) (madmin.Credentials, error) {
func (ac AdminClientMock) addServiceAccount(ctx context.Context, policy string, user string, accessKey string, secretKey string, description string, name string, expiry *time.Time, status string) (madmin.Credentials, error) {
return minioAddServiceAccountMock(ctx, policy, user, accessKey, secretKey, description, name, expiry, status)
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -24,11 +24,11 @@ import (
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/console/api/operations"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
madmin "github.com/minio/madmin-go/v3"
cfgApi "github.com/minio/console/restapi/operations/configuration"
cfgApi "github.com/minio/console/api/operations/configuration"
)
func registerConfigHandlers(api *operations.ConsoleAPI) {
@@ -269,7 +269,6 @@ func resetConfigResponse(session *models.Principal, params cfgApi.ResetConfigPar
adminClient := AdminClient{Client: mAdmin}
err = resetConfig(ctx, adminClient, &params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -63,7 +63,7 @@ func TestListConfig(t *testing.T) {
}
expectedKeysDesc := mockConfigList.KeysHelp
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return mockConfigList, nil
}
configList, err := listConfig(adminClient)
@@ -80,7 +80,7 @@ func TestListConfig(t *testing.T) {
// Test-2 : listConfig() Return error and see that the error is handled correctly and returned
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return madmin.Help{}, errors.New("error")
}
_, err = listConfig(adminClient)
@@ -94,7 +94,7 @@ func TestSetConfig(t *testing.T) {
adminClient := AdminClientMock{}
function := "setConfig()"
// mock function response from setConfig()
minioSetConfigKVMock = func(kv string) (restart bool, err error) {
minioSetConfigKVMock = func(_ string) (restart bool, err error) {
return false, nil
}
configName := "notify_postgres"
@@ -119,7 +119,7 @@ func TestSetConfig(t *testing.T) {
assert.Equal(restart, false)
// Test-2 : setConfig() returns error, handle properly
minioSetConfigKVMock = func(kv string) (restart bool, err error) {
minioSetConfigKVMock = func(_ string) (restart bool, err error) {
return false, errors.New("error")
}
restart, err = setConfig(ctx, adminClient, &configName, kvs)
@@ -129,7 +129,7 @@ func TestSetConfig(t *testing.T) {
assert.Equal(restart, false)
// Test-4 : setConfig() set config, need restart
minioSetConfigKVMock = func(kv string) (restart bool, err error) {
minioSetConfigKVMock = func(_ string) (restart bool, err error) {
return true, nil
}
restart, err = setConfig(ctx, adminClient, &configName, kvs)
@@ -144,7 +144,7 @@ func TestDelConfig(t *testing.T) {
adminClient := AdminClientMock{}
function := "resetConfig()"
// mock function response from setConfig()
minioDelConfigKVMock = func(name string) (err error) {
minioDelConfigKVMock = func(_ string) (err error) {
return nil
}
configName := "region"
@@ -158,7 +158,7 @@ func TestDelConfig(t *testing.T) {
}
// Test-2 : resetConfig() returns error, handle properly
minioDelConfigKVMock = func(name string) (err error) {
minioDelConfigKVMock = func(_ string) (err error) {
return errors.New("error")
}
@@ -220,7 +220,7 @@ func Test_buildConfig(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
if got := buildConfig(tt.args.configName, tt.args.kvs); !reflect.DeepEqual(got, tt.want) {
t.Errorf("buildConfig() = %s, want %s", *got, *tt.want)
}
@@ -260,7 +260,7 @@ func Test_setConfigWithARN(t *testing.T) {
},
arn: "1",
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
wantErr: false,
@@ -280,7 +280,7 @@ func Test_setConfigWithARN(t *testing.T) {
},
arn: "1",
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return true, nil
},
wantErr: false,
@@ -300,7 +300,7 @@ func Test_setConfigWithARN(t *testing.T) {
},
arn: "",
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
wantErr: false,
@@ -320,7 +320,7 @@ func Test_setConfigWithARN(t *testing.T) {
},
arn: "",
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, errors.New("error")
},
wantErr: true,
@@ -328,7 +328,7 @@ func Test_setConfigWithARN(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
// mock function response from setConfig()
minioSetConfigKVMock = tt.mockSetConfig
restart, err := setConfigWithARNAccountID(tt.args.ctx, tt.args.client, tt.args.configName, tt.args.kvs, tt.args.arn)
@@ -361,7 +361,7 @@ func Test_getConfig(t *testing.T) {
},
mock: func() {
// mock function response from getConfig()
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
return []byte(`notify_postgres:_ connection_string="host=localhost dbname=minio_events user=postgres password=password port=5432 sslmode=disable" table=bucketevents`), nil
}
@@ -407,7 +407,7 @@ func Test_getConfig(t *testing.T) {
KeysHelp: configListMock,
}
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return mockConfigList, nil
}
},
@@ -435,7 +435,7 @@ func Test_getConfig(t *testing.T) {
},
mock: func() {
// mock function response from getConfig()
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
return []byte(`notify_postgres:_`), nil
}
@@ -481,7 +481,7 @@ func Test_getConfig(t *testing.T) {
KeysHelp: configListMock,
}
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return mockConfigList, nil
}
},
@@ -496,7 +496,7 @@ func Test_getConfig(t *testing.T) {
},
mock: func() {
// mock function response from getConfig()
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
x := make(map[string]string)
x["x"] = "x"
j, _ := json.Marshal(x)
@@ -545,7 +545,7 @@ func Test_getConfig(t *testing.T) {
KeysHelp: configListMock,
}
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return mockConfigList, nil
}
},
@@ -560,13 +560,13 @@ func Test_getConfig(t *testing.T) {
},
mock: func() {
// mock function response from getConfig()
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
return nil, errors.New("invalid config")
}
mockConfigList := madmin.Help{}
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return mockConfigList, nil
}
},
@@ -581,11 +581,11 @@ func Test_getConfig(t *testing.T) {
},
mock: func() {
// mock function response from getConfig()
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
return nil, errors.New("invalid config")
}
// mock function response from listConfig()
minioHelpConfigKVMock = func(subSys, key string, envOnly bool) (madmin.Help, error) {
minioHelpConfigKVMock = func(_, _ string, _ bool) (madmin.Help, error) {
return madmin.Help{}, errors.New("no help")
}
},
@@ -595,7 +595,7 @@ func Test_getConfig(t *testing.T) {
}
for _, tt := range tests {
tt.mock()
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
got, err := getConfig(context.Background(), tt.args.client, tt.args.name)
if (err != nil) != tt.wantErr {
t.Errorf("getConfig() error = %v, wantErr %v", err, tt.wantErr)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -40,7 +40,7 @@ func TestAdminConsoleLog(t *testing.T) {
// Test-1: Serve Console with no errors until Console finishes sending
// define mock function behavior for minio server Console
minioGetLogsMock = func(ctx context.Context, node string, lineCnt int, logKind string) <-chan madmin.LogInfo {
minioGetLogsMock = func(_ context.Context, _ string, _ int, _ string) <-chan madmin.LogInfo {
ch := make(chan madmin.LogInfo)
// Only success, start a routine to start reading line by line.
go func(ch chan<- madmin.LogInfo) {
@@ -58,7 +58,7 @@ func TestAdminConsoleLog(t *testing.T) {
}
writesCount := 1
// mock connection WriteMessage() no error
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, data []byte) error {
// emulate that receiver gets the message written
var t madmin.LogInfo
_ = json.Unmarshal(data, &t)
@@ -82,7 +82,7 @@ func TestAdminConsoleLog(t *testing.T) {
}
// Test-2: if error happens while writing, return error
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, _ []byte) error {
return fmt.Errorf("error on write")
}
if err := startConsoleLog(ctx, mockWSConn, adminClient, LogRequest{node: "", logType: "all"}); assert.Error(err) {
@@ -91,7 +91,7 @@ func TestAdminConsoleLog(t *testing.T) {
// Test-3: error happens on GetLogs Minio, Console should stop
// and error shall be returned.
minioGetLogsMock = func(ctx context.Context, node string, lineCnt int, logKind string) <-chan madmin.LogInfo {
minioGetLogsMock = func(_ context.Context, _ string, _ int, _ string) <-chan madmin.LogInfo {
ch := make(chan madmin.LogInfo)
// Only success, start a routine to start reading line by line.
go func(ch chan<- madmin.LogInfo) {
@@ -108,7 +108,7 @@ func TestAdminConsoleLog(t *testing.T) {
}(ch)
return ch
}
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, _ []byte) error {
return nil
}
if err := startConsoleLog(ctx, mockWSConn, adminClient, LogRequest{node: "", logType: "all"}); assert.Error(err) {

View File

@@ -14,18 +14,18 @@
// 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 restapi
package api
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/pkg/utils"
"github.com/minio/console/restapi/operations"
"github.com/minio/madmin-go/v3"
groupApi "github.com/minio/console/restapi/operations/group"
groupApi "github.com/minio/console/api/operations/group"
"github.com/minio/console/models"
)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -130,7 +130,7 @@ func TestGroupInfo(t *testing.T) {
Status: "enabled",
}
// mock function response from updateGroupMembers()
minioGetGroupDescriptionMock = func(group string) (*madmin.GroupDesc, error) {
minioGetGroupDescriptionMock = func(_ string) (*madmin.GroupDesc, error) {
return mockResponse, nil
}
function := "groupInfo()"
@@ -144,7 +144,7 @@ func TestGroupInfo(t *testing.T) {
assert.Equal("enabled", info.Status)
// Test-2 : groupInfo() Return error and see that the error is handled correctly and returned
minioGetGroupDescriptionMock = func(group string) (*madmin.GroupDesc, error) {
minioGetGroupDescriptionMock = func(_ string) (*madmin.GroupDesc, error) {
return nil, errors.New("error")
}
_, err = groupInfo(ctx, adminClient, groupName)
@@ -226,7 +226,7 @@ func TestUpdateGroup(t *testing.T) {
// the function twice but the second time returned an error
is2ndRunGroupInfo := false
// mock function response from updateGroupMembers()
minioGetGroupDescriptionMock = func(group string) (*madmin.GroupDesc, error) {
minioGetGroupDescriptionMock = func(_ string) (*madmin.GroupDesc, error) {
if is2ndRunGroupInfo {
return mockResponseAfterUpdate, nil
}
@@ -236,7 +236,7 @@ func TestUpdateGroup(t *testing.T) {
minioUpdateGroupMembersMock = func(madmin.GroupAddRemove) error {
return nil
}
minioSetGroupStatusMock = func(group string, status madmin.GroupStatus) error {
minioSetGroupStatusMock = func(_ string, _ madmin.GroupStatus) error {
return nil
}
groupUpdated, err := groupUpdate(ctx, adminClient, groupName, expectedGroupUpdate)
@@ -258,7 +258,7 @@ func TestSetGroupStatus(t *testing.T) {
defer cancel()
// Test-1: setGroupStatus() update valid disabled status
expectedStatus := "disabled"
minioSetGroupStatusMock = func(group string, status madmin.GroupStatus) error {
minioSetGroupStatusMock = func(_ string, _ madmin.GroupStatus) error {
return nil
}
if err := setGroupStatus(ctx, adminClient, groupName, expectedStatus); err != nil {
@@ -266,7 +266,7 @@ func TestSetGroupStatus(t *testing.T) {
}
// Test-2: setGroupStatus() update valid enabled status
expectedStatus = "enabled"
minioSetGroupStatusMock = func(group string, status madmin.GroupStatus) error {
minioSetGroupStatusMock = func(_ string, _ madmin.GroupStatus) error {
return nil
}
if err := setGroupStatus(ctx, adminClient, groupName, expectedStatus); err != nil {
@@ -274,7 +274,7 @@ func TestSetGroupStatus(t *testing.T) {
}
// Test-3: setGroupStatus() update invalid status, should send error
expectedStatus = "invalid"
minioSetGroupStatusMock = func(group string, status madmin.GroupStatus) error {
minioSetGroupStatusMock = func(_ string, _ madmin.GroupStatus) error {
return nil
}
if err := setGroupStatus(ctx, adminClient, groupName, expectedStatus); assert.Error(err) {
@@ -282,7 +282,7 @@ func TestSetGroupStatus(t *testing.T) {
}
// Test-4: setGroupStatus() handler error correctly
expectedStatus = "enabled"
minioSetGroupStatusMock = func(group string, status madmin.GroupStatus) error {
minioSetGroupStatusMock = func(_ string, _ madmin.GroupStatus) error {
return errors.New("error")
}
if err := setGroupStatus(ctx, adminClient, groupName, expectedStatus); assert.Error(err) {

View File

@@ -14,25 +14,24 @@
// 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 restapi
package api
import (
"bytes"
"context"
b64 "encoding/base64"
"encoding/json"
"errors"
"fmt"
"net/http"
"strings"
"net/url"
"os"
"time"
"github.com/minio/console/pkg/logger"
"github.com/minio/console/pkg/utils"
"github.com/klauspost/compress/gzip"
xhttp "github.com/minio/console/pkg/http"
subnet "github.com/minio/console/pkg/subnet"
"github.com/minio/madmin-go/v3"
mc "github.com/minio/mc/cmd"
"github.com/minio/websocket"
)
@@ -44,26 +43,12 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
}
// Fetch info of all servers (cluster or single server)
healthDataTypes := []madmin.HealthDataType{
madmin.HealthDataTypeMinioInfo,
madmin.HealthDataTypeMinioConfig,
madmin.HealthDataTypeSysCPU,
madmin.HealthDataTypeSysDriveHw,
madmin.HealthDataTypeSysDocker,
madmin.HealthDataTypeSysOsInfo,
madmin.HealthDataTypeSysLoad,
madmin.HealthDataTypeSysMem,
madmin.HealthDataTypeSysNet,
madmin.HealthDataTypeSysProcess,
}
var err error
// Fetch info of all servers (cluster or single server)
healthInfo, version, err := client.serverHealthInfo(ctx, healthDataTypes, *deadline)
healthInfo, version, err := client.serverHealthInfo(ctx, *deadline)
if err != nil {
return err
}
compressedDiag, err := tarGZ(healthInfo, version)
compressedDiag, err := mc.TarGZHealthInfo(healthInfo, version)
if err != nil {
return err
}
@@ -75,11 +60,11 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
}
ctx = context.WithValue(ctx, utils.ContextClientIP, conn.remoteAddress())
subnetResp, err := sendHealthInfoToSubnet(ctx, healthInfo, client)
err = sendHealthInfoToSubnet(ctx, compressedDiag, client)
report := messageReport{
Encoded: encodedDiag,
ServerHealthInfo: healthInfo,
SubnetResponse: subnetResp,
SubnetResponse: mc.SubnetBaseURL() + "/health",
}
if err != nil {
report.SubnetResponse = fmt.Sprintf("Error: %s", err.Error())
@@ -94,31 +79,6 @@ func startHealthInfo(ctx context.Context, conn WSConn, client MinioAdmin, deadli
return conn.writeMessage(websocket.TextMessage, message)
}
// compress and tar MinIO diagnostics output
func tarGZ(healthInfo interface{}, version string) ([]byte, error) {
buffer := bytes.NewBuffer(nil)
gzWriter := gzip.NewWriter(buffer)
enc := json.NewEncoder(gzWriter)
header := struct {
Version string `json:"version"`
}{Version: version}
if err := enc.Encode(header); err != nil {
return nil, err
}
if err := enc.Encode(healthInfo); err != nil {
return nil, err
}
err := gzWriter.Close()
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
// getHealthInfoOptionsFromReq gets duration for startHealthInfo request
// path come as : `/health-info?deadline=2h`
func getHealthInfoOptionsFromReq(req *http.Request) (*time.Duration, error) {
@@ -129,16 +89,27 @@ func getHealthInfoOptionsFromReq(req *http.Request) (*time.Duration, error) {
return &deadlineDuration, nil
}
func sendHealthInfoToSubnet(ctx context.Context, healthInfo interface{}, client MinioAdmin) (string, error) {
filename := fmt.Sprintf("health_%d.json", time.Now().Unix())
func updateMcGlobals(subnetTokenConfig subnet.LicenseTokenConfig) error {
mc.GlobalDevMode = getConsoleDevMode()
if len(subnetTokenConfig.Proxy) > 0 {
proxyURL, e := url.Parse(subnetTokenConfig.Proxy)
if e != nil {
return e
}
mc.GlobalSubnetProxyURL = proxyURL
}
return nil
}
clientIP := utils.ClientIPFromContext(ctx)
subnetUploadURL := subnet.UploadURL("health", filename)
subnetHTTPClient := &xhttp.Client{Client: GetConsoleHTTPClient("", clientIP)}
func sendHealthInfoToSubnet(ctx context.Context, compressedHealthInfo []byte, client MinioAdmin) error {
filename := fmt.Sprintf("health_%d.json.gz", time.Now().Unix())
subnetTokenConfig, e := GetSubnetKeyFromMinIOConfig(ctx, client)
if e != nil {
return "", e
return e
}
e = updateMcGlobals(*subnetTokenConfig)
if e != nil {
return e
}
var apiKey string
if len(subnetTokenConfig.APIKey) != 0 {
@@ -146,32 +117,37 @@ func sendHealthInfoToSubnet(ctx context.Context, healthInfo interface{}, client
} else {
apiKey, e = subnet.GetSubnetAPIKeyUsingLicense(subnetTokenConfig.License)
if e != nil {
return "", e
return e
}
}
headers := subnet.UploadAuthHeaders(apiKey)
uploadInfo, formDataType, e := subnet.ProcessUploadInfo(healthInfo, "health", filename)
e = os.WriteFile(filename, compressedHealthInfo, 0o666)
if e != nil {
return "", e
return e
}
headers := mc.SubnetAPIKeyAuthHeaders(apiKey)
resp, e := (&mc.SubnetFileUploader{
FilePath: filename,
ReqURL: mc.SubnetUploadURL("health"),
Headers: headers,
DeleteAfterUpload: true,
}).UploadFileToSubnet()
if e != nil {
// file gets deleted only if upload is successful
// so we delete explicitly here as we already have the bytes
logger.LogIf(ctx, os.Remove(filename))
return e
}
resp, e := subnet.UploadFileToSubnet(uploadInfo, subnetHTTPClient, subnetUploadURL, headers, formDataType)
if e != nil {
return "", e
}
type SubnetResponse struct {
ClusterURL string `json:"cluster_url,omitempty"`
LicenseV2 string `json:"license_v2,omitempty"`
APIKey string `json:"api_key,omitempty"`
}
var subnetResp SubnetResponse
e = json.Unmarshal([]byte(resp), &subnetResp)
if e != nil {
return "", e
}
if len(subnetResp.ClusterURL) != 0 {
subnetClusterURL := strings.ReplaceAll(subnetResp.ClusterURL, "%2f", "/")
return subnetClusterURL, nil
return e
}
return "", ErrSubnetUploadFail
return nil
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -51,7 +51,7 @@ func Test_serverHealthInfo(t *testing.T) {
args: args{
deadline: deadlineDuration,
mockMessages: []madmin.HealthInfo{{}, {}},
wsWriteMock: func(messageType int, data []byte) error {
wsWriteMock: func(_ int, data []byte) error {
// mock connection WriteMessage() no error
// emulate that receiver gets the message written
var t madmin.HealthInfo
@@ -67,7 +67,7 @@ func Test_serverHealthInfo(t *testing.T) {
args: args{
deadline: deadlineDuration,
mockMessages: []madmin.HealthInfo{{}},
wsWriteMock: func(messageType int, data []byte) error {
wsWriteMock: func(_ int, data []byte) error {
// mock connection WriteMessage() no error
// emulate that receiver gets the message written
var t madmin.HealthInfo
@@ -83,7 +83,7 @@ func Test_serverHealthInfo(t *testing.T) {
args: args{
deadline: deadlineDuration,
mockMessages: []madmin.HealthInfo{{}},
wsWriteMock: func(messageType int, data []byte) error {
wsWriteMock: func(_ int, data []byte) error {
// mock connection WriteMessage() no error
// emulate that receiver gets the message written
var t madmin.HealthInfo
@@ -102,7 +102,7 @@ func Test_serverHealthInfo(t *testing.T) {
Error: "error on healthInfo",
},
},
wsWriteMock: func(messageType int, data []byte) error {
wsWriteMock: func(_ int, data []byte) error {
// mock connection WriteMessage() no error
// emulate that receiver gets the message written
var t madmin.HealthInfo
@@ -115,12 +115,12 @@ func Test_serverHealthInfo(t *testing.T) {
}
for _, tt := range tests {
tt := tt
t.Run(tt.test, func(t *testing.T) {
t.Run(tt.test, func(_ *testing.T) {
// make testReceiver channel
testReceiver = make(chan madmin.HealthInfo, len(tt.args.mockMessages))
// mock function same for all tests, changes mockMessages
minioServerHealthInfoMock = func(ctx context.Context, healthDataTypes []madmin.HealthDataType,
deadline time.Duration,
minioServerHealthInfoMock = func(_ context.Context,
_ time.Duration,
) (interface{}, string, error) {
info := tt.args.mockMessages[0]
return info, madmin.HealthInfoVersion, nil

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
import (
"context"
@@ -23,9 +23,9 @@ import (
"time"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/api/operations/idp"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/idp"
"github.com/minio/madmin-go/v3"
)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -27,9 +27,9 @@ import (
"github.com/minio/madmin-go/v3"
"github.com/minio/console/api/operations"
"github.com/minio/console/api/operations/idp"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/restapi/operations/idp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)
@@ -46,7 +46,7 @@ type IDPTestSuite struct {
func (suite *IDPTestSuite) SetupSuite() {
suite.assert = assert.New(suite.T())
suite.adminClient = AdminClientMock{}
minioServiceRestartMock = func(ctx context.Context) error {
minioServiceRestartMock = func(_ context.Context) error {
return nil
}
}
@@ -270,7 +270,7 @@ func TestGetEntitiesResult(t *testing.T) {
GroupMappings: groupsMap,
UserMappings: usersMap,
}
minioGetLDAPPolicyEntitiesMock = func(ctx context.Context, query madmin.PolicyEntitiesQuery) (madmin.PolicyEntitiesResult, error) {
minioGetLDAPPolicyEntitiesMock = func(_ context.Context, _ madmin.PolicyEntitiesQuery) (madmin.PolicyEntitiesResult, error) {
return mockResponse, nil
}
@@ -308,7 +308,7 @@ func TestGetEntitiesResult(t *testing.T) {
}
// Test-2: getEntitiesResult error is returned from getLDAPPolicyEntities()
minioGetLDAPPolicyEntitiesMock = func(ctx context.Context, query madmin.PolicyEntitiesQuery) (madmin.PolicyEntitiesResult, error) {
minioGetLDAPPolicyEntitiesMock = func(_ context.Context, _ madmin.PolicyEntitiesQuery) (madmin.PolicyEntitiesResult, error) {
return madmin.PolicyEntitiesResult{}, errors.New("error")
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -31,9 +31,9 @@ import (
"github.com/minio/console/pkg/utils"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
systemApi "github.com/minio/console/api/operations/system"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
systemApi "github.com/minio/console/restapi/operations/system"
)
func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
@@ -46,7 +46,7 @@ func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
return systemApi.NewAdminInfoOK().WithPayload(infoResp)
})
// return single widget results
api.SystemDashboardWidgetDetailsHandler = systemApi.DashboardWidgetDetailsHandlerFunc(func(params systemApi.DashboardWidgetDetailsParams, session *models.Principal) middleware.Responder {
api.SystemDashboardWidgetDetailsHandler = systemApi.DashboardWidgetDetailsHandlerFunc(func(params systemApi.DashboardWidgetDetailsParams, _ *models.Principal) middleware.Responder {
infoResp, err := getAdminInfoWidgetResponse(params)
if err != nil {
return systemApi.NewDashboardWidgetDetailsDefault(err.Code).WithPayload(err.APIError)
@@ -775,7 +775,7 @@ var widgets = []Metric{
},
Targets: []Target{
{
Expr: `minio_cluster_drive_free_inodes{$__query}`,
Expr: `minio_node_drive_free_inodes{$__query}`,
LegendFormat: "Free Inodes [{{server}}:{{drive}}]",
},
},
@@ -881,7 +881,10 @@ func getAdminInfoResponse(session *models.Principal, params systemApi.AdminInfoP
prometheusURL := ""
if !*params.DefaultOnly {
prometheusURL = getPrometheusURL()
promURL := getPrometheusURL()
if promURL != "" {
prometheusURL = promURL
}
}
mAdmin, err := NewMinioAdminClient(params.HTTPRequest.Context(), session)
@@ -991,8 +994,6 @@ func unmarshalPrometheus(ctx context.Context, httpClnt *http.Client, endpoint st
}
func testPrometheusURL(ctx context.Context, url string) bool {
clientIP := utils.ClientIPFromContext(ctx)
httpClnt := GetConsoleHTTPClient(url, clientIP)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url+"/-/healthy", nil)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("error Building Request: (%v)", err))
@@ -1000,11 +1001,13 @@ func testPrometheusURL(ctx context.Context, url string) bool {
}
prometheusBearer := getPrometheusAuthToken()
if prometheusBearer != "" {
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", prometheusBearer))
}
clientIP := utils.ClientIPFromContext(ctx)
httpClnt := GetConsoleHTTPClient(clientIP)
response, err := httpClnt.Do(req)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("default Prometheus URL not reachable, trying root testing: (%v)", err))
@@ -1047,7 +1050,7 @@ func getWidgetDetails(ctx context.Context, prometheusURL string, selector string
return nil, ErrorWithContext(ctx, errors.New("prometheus URL is unreachable"))
}
clientIP := utils.ClientIPFromContext(ctx)
httpClnt := GetConsoleHTTPClient(prometheusURL, clientIP)
httpClnt := GetConsoleHTTPClient(clientIP)
labelResultsCh := make(chan LabelResults)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -25,9 +25,9 @@ import (
"github.com/minio/console/pkg/utils"
"github.com/minio/console/api/operations"
systemApi "github.com/minio/console/api/operations/system"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
systemApi "github.com/minio/console/restapi/operations/system"
"github.com/minio/madmin-go/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@@ -46,7 +46,7 @@ type AdminInfoTestSuite struct {
func (suite *AdminInfoTestSuite) SetupSuite() {
suite.assert = assert.New(suite.T())
suite.adminClient = AdminClientMock{}
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{
Servers: []madmin.ServerProperties{{
Disks: []madmin.Disk{{}},

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"encoding/base64"
@@ -26,9 +26,9 @@ import (
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
inspectApi "github.com/minio/console/api/operations/inspect"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
inspectApi "github.com/minio/console/restapi/operations/inspect"
"github.com/minio/madmin-go/v3"
"github.com/secure-io/sio-go"
)
@@ -120,7 +120,7 @@ func processInspectResponse(params *inspectApi.InspectParams, k []byte, r io.Rea
_, err := io.Copy(w, r)
if err != nil {
LogError("Unable to write all the data: %v", err)
LogError("unable to write all the data: %v", err)
}
}
}

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
import (
"context"
@@ -23,9 +23,9 @@ import (
"sort"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
kmsAPI "github.com/minio/console/api/operations/k_m_s"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
kmsAPI "github.com/minio/console/restapi/operations/k_m_s"
"github.com/minio/madmin-go/v3"
)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -23,9 +23,9 @@ import (
"os"
"testing"
"github.com/minio/console/api/operations"
kmsAPI "github.com/minio/console/api/operations/k_m_s"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
kmsAPI "github.com/minio/console/restapi/operations/k_m_s"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

View File

@@ -14,15 +14,15 @@
// 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 restapi
package api
import (
"context"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
systemApi "github.com/minio/console/api/operations/system"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
systemApi "github.com/minio/console/restapi/operations/system"
)
func registerNodesHandler(api *operations.ConsoleAPI) {

View File

@@ -14,16 +14,16 @@
// 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 restapi
package api
import (
"context"
"errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
configurationApi "github.com/minio/console/api/operations/configuration"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
configurationApi "github.com/minio/console/restapi/operations/configuration"
)
func registerAdminNotificationEndpointsHandlers(api *operations.ConsoleAPI) {

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -24,8 +24,8 @@ import (
"github.com/go-openapi/swag"
cfgApi "github.com/minio/console/api/operations/configuration"
"github.com/minio/console/models"
cfgApi "github.com/minio/console/restapi/operations/configuration"
)
func Test_addNotificationEndpoint(t *testing.T) {
@@ -61,7 +61,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -94,7 +94,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, errors.New("error")
},
want: nil,
@@ -118,7 +118,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -149,7 +149,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -178,7 +178,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -208,7 +208,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -240,7 +240,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -273,7 +273,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -305,7 +305,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -335,7 +335,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -365,7 +365,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -397,7 +397,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return false, errors.New("invalid config")
},
want: nil,
@@ -421,7 +421,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
},
},
mockSetConfig: func(kv string) (restart bool, err error) {
mockSetConfig: func(_ string) (restart bool, err error) {
return true, nil
},
want: &models.SetNotificationEndpointResponse{
@@ -438,7 +438,7 @@ func Test_addNotificationEndpoint(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
// mock function response from setConfig()
minioSetConfigKVMock = tt.mockSetConfig
got, err := addNotificationEndpoint(tt.args.ctx, tt.args.client, tt.args.params)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -97,11 +97,11 @@ func TestWSRewindObjects(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
mcListMock = func(ctx context.Context, opts mc.ListOptions) <-chan *mc.ClientContent {
mcListMock = func(_ context.Context, _ mc.ListOptions) <-chan *mc.ClientContent {
ch := make(chan *mc.ClientContent)
go func() {
defer close(ch)
@@ -206,11 +206,11 @@ func TestWSListObjects(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
minioListObjectsMock = func(ctx context.Context, bucket string, opts minio.ListObjectsOptions) <-chan minio.ObjectInfo {
minioListObjectsMock = func(_ context.Context, _ string, _ minio.ListObjectsOptions) <-chan minio.ObjectInfo {
ch := make(chan minio.ObjectInfo)
go func() {
defer close(ch)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"bytes"
@@ -24,17 +24,17 @@ import (
"sort"
"strings"
bucketApi "github.com/minio/console/api/operations/bucket"
policyApi "github.com/minio/console/api/operations/policy"
"github.com/minio/console/pkg/utils"
bucketApi "github.com/minio/console/restapi/operations/bucket"
policyApi "github.com/minio/console/restapi/operations/policy"
s3 "github.com/minio/minio-go/v7"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
policies "github.com/minio/console/restapi/policy"
policies "github.com/minio/console/api/policy"
)
func registersPoliciesHandler(api *operations.ConsoleAPI) {

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"bytes"
@@ -26,7 +26,7 @@ import (
"testing"
"github.com/minio/console/models"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
"github.com/stretchr/testify/assert"
)
@@ -83,7 +83,7 @@ func TestRemovePolicy(t *testing.T) {
adminClient := AdminClientMock{}
// Test-1 : removePolicy() remove an existing policy
policyToRemove := "console-policy"
minioRemovePolicyMock = func(name string) error {
minioRemovePolicyMock = func(_ string) error {
return nil
}
function := "removePolicy()"
@@ -91,7 +91,7 @@ func TestRemovePolicy(t *testing.T) {
t.Errorf("Failed on %s:, error occurred: %s", function, err.Error())
}
// Test-2 : removePolicy() Return error and see that the error is handled correctly and returned
minioRemovePolicyMock = func(name string) error {
minioRemovePolicyMock = func(_ string) error {
return errors.New("error")
}
if err := removePolicy(ctx, adminClient, policyToRemove); funcAssert.Error(err) {
@@ -106,10 +106,10 @@ func TestAddPolicy(t *testing.T) {
adminClient := AdminClientMock{}
policyName := "new-policy"
policyDefinition := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::*\"]}]}"
minioAddPolicyMock = func(name string, policy *iampolicy.Policy) error {
minioAddPolicyMock = func(_ string, _ *iampolicy.Policy) error {
return nil
}
minioGetPolicyMock = func(name string) (*iampolicy.Policy, error) {
minioGetPolicyMock = func(_ string) (*iampolicy.Policy, error) {
policy := "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"s3:GetBucketLocation\",\"s3:GetObject\",\"s3:ListAllMyBuckets\"],\"Resource\":[\"arn:aws:s3:::*\"]}]}"
iamp, err := iampolicy.ParseConfig(bytes.NewReader([]byte(policy)))
if err != nil {
@@ -138,17 +138,17 @@ func TestAddPolicy(t *testing.T) {
funcAssert.Equal(expectedPolicy, actualPolicy)
}
// Test-2 : addPolicy() got an error while adding policy
minioAddPolicyMock = func(name string, policy *iampolicy.Policy) error {
minioAddPolicyMock = func(_ string, _ *iampolicy.Policy) error {
return errors.New("error")
}
if _, err := addPolicy(ctx, adminClient, policyName, policyDefinition); funcAssert.Error(err) {
funcAssert.Equal("error", err.Error())
}
// Test-3 : addPolicy() got an error while retrieving policy
minioAddPolicyMock = func(name string, policy *iampolicy.Policy) error {
minioAddPolicyMock = func(_ string, _ *iampolicy.Policy) error {
return nil
}
minioGetPolicyMock = func(name string) (*iampolicy.Policy, error) {
minioGetPolicyMock = func(_ string) (*iampolicy.Policy, error) {
return nil, errors.New("error")
}
if _, err := addPolicy(ctx, adminClient, policyName, policyDefinition); funcAssert.Error(err) {
@@ -164,7 +164,7 @@ func TestSetPolicy(t *testing.T) {
policyName := "readOnly"
entityName := "alevsk"
entityObject := models.PolicyEntityUser
minioSetPolicyMock = func(policyName, entityName string, isGroup bool) error {
minioSetPolicyMock = func(_, _ string, _ bool) error {
return nil
}
// Test-1 : SetPolicy() set policy to user
@@ -181,7 +181,7 @@ func TestSetPolicy(t *testing.T) {
}
// Test-3 : SetPolicy() set policy to user and get error
entityObject = models.PolicyEntityUser
minioSetPolicyMock = func(policyName, entityName string, isGroup bool) error {
minioSetPolicyMock = func(_, _ string, _ bool) error {
return errors.New("error")
}
if err := SetPolicy(ctx, adminClient, policyName, entityName, entityObject); funcAssert.Error(err) {
@@ -189,7 +189,7 @@ func TestSetPolicy(t *testing.T) {
}
// Test-4 : SetPolicy() set policy to group and get error
entityObject = models.PolicyEntityGroup
minioSetPolicyMock = func(policyName, entityName string, isGroup bool) error {
minioSetPolicyMock = func(_, _ string, _ bool) error {
return errors.New("error")
}
if err := SetPolicy(ctx, adminClient, policyName, entityName, entityObject); funcAssert.Error(err) {
@@ -219,7 +219,7 @@ func Test_SetPolicyMultiple(t *testing.T) {
policyName: "readonly",
users: []models.IamEntity{"user1", "user2"},
groups: []models.IamEntity{"group1", "group2"},
setPolicyFunc: func(policyName, entityName string, isGroup bool) error {
setPolicyFunc: func(_, _ string, _ bool) error {
return nil
},
},
@@ -231,7 +231,7 @@ func Test_SetPolicyMultiple(t *testing.T) {
policyName: "readonly",
users: []models.IamEntity{"user1", "user2"},
groups: []models.IamEntity{"group1", "group2"},
setPolicyFunc: func(policyName, entityName string, isGroup bool) error {
setPolicyFunc: func(_, _ string, _ bool) error {
return errors.New("error set")
},
},
@@ -244,7 +244,7 @@ func Test_SetPolicyMultiple(t *testing.T) {
policyName: "readonly",
users: []models.IamEntity{},
groups: []models.IamEntity{},
setPolicyFunc: func(policyName, entityName string, isGroup bool) error {
setPolicyFunc: func(_, _ string, _ bool) error {
return nil
},
},
@@ -252,7 +252,7 @@ func Test_SetPolicyMultiple(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
minioSetPolicyMock = tt.args.setPolicyFunc
got := setPolicyMultipleEntities(ctx, adminClient, tt.args.policyName, tt.args.users, tt.args.groups)
if !reflect.DeepEqual(got, tt.errorExpected) {
@@ -373,7 +373,7 @@ func Test_policyMatchesBucket(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
if got := policyMatchesBucket(tt.args.ctx, tt.args.policy, tt.args.bucket); got != tt.want {
t.Errorf("policyMatchesBucket() = %v, want %v", got, tt.want)
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"bytes"
@@ -52,7 +52,7 @@ func TestStartProfiling(t *testing.T) {
// Test-1 : startProfiling() Get response from MinIO server with one profiling object without errors
// mock function response from startProfiling()
minioStartProfiling = func(profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
minioStartProfiling = func(_ madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
return []madmin.StartProfilingResult{
{
NodeName: "http://127.0.0.1:9000/",
@@ -71,7 +71,7 @@ func TestStartProfiling(t *testing.T) {
return &ClosingBuffer{bytes.NewBufferString("In memory string eaeae")}, nil
}
// mock function response from mockConn.writeMessage()
connWriteMessageMock = func(messageType int, p []byte) error {
connWriteMessageMock = func(_ int, _ []byte) error {
return nil
}
err := startProfiling(ctx, mockWSConn, adminClient, testOptions)
@@ -82,7 +82,7 @@ func TestStartProfiling(t *testing.T) {
// Test-2 : startProfiling() Correctly handles errors returned by MinIO
// mock function response from startProfiling()
minioStartProfiling = func(profiler madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
minioStartProfiling = func(_ madmin.ProfilerType) ([]madmin.StartProfilingResult, error) {
return nil, errors.New("error")
}
err = startProfiling(ctx, mockWSConn, adminClient, testOptions)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -27,10 +27,10 @@ import (
"github.com/minio/console/pkg/utils"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
release "github.com/minio/console/api/operations/release"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
release "github.com/minio/console/restapi/operations/release"
"github.com/minio/pkg/v2/env"
"github.com/minio/pkg/v3/env"
)
var (
@@ -97,7 +97,7 @@ func getReleases(endpoint, repo, currentRelease, search, filter, clientIP string
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")
client := GetConsoleHTTPClient("", clientIP)
client := GetConsoleHTTPClient(clientIP)
client.Timeout = time.Second * 5
resp, err := client.Do(req)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"encoding/json"
@@ -24,9 +24,9 @@ import (
"os"
"testing"
"github.com/minio/console/api/operations"
release "github.com/minio/console/api/operations/release"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
release "github.com/minio/console/restapi/operations/release"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -30,9 +30,9 @@ import (
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/console/api/operations"
bucketApi "github.com/minio/console/api/operations/bucket"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
bucketApi "github.com/minio/console/restapi/operations/bucket"
"github.com/minio/minio-go/v7/pkg/replication"
)
@@ -90,7 +90,7 @@ func registerAdminBucketRemoteHandlers(api *operations.ConsoleAPI) {
})
// list external buckets
api.BucketListExternalBucketsHandler = bucketApi.ListExternalBucketsHandlerFunc(func(params bucketApi.ListExternalBucketsParams, session *models.Principal) middleware.Responder {
api.BucketListExternalBucketsHandler = bucketApi.ListExternalBucketsHandlerFunc(func(params bucketApi.ListExternalBucketsParams, _ *models.Principal) middleware.Responder {
response, err := listExternalBucketsResponse(params)
if err != nil {
return bucketApi.NewListExternalBucketsDefault(err.Code).WithPayload(err.APIError)
@@ -292,7 +292,7 @@ func addRemoteBucket(ctx context.Context, client MinioAdmin, params models.Creat
return bucketARN, err
}
func addBucketReplicationItem(ctx context.Context, session *models.Principal, minClient minioClient, bucketName, prefix, destinationARN string, repDelMark, repDels, repMeta bool, tags string, priority int32, storageClass string) error {
func addBucketReplicationItem(ctx context.Context, session *models.Principal, minClient minioClient, bucketName, prefix, destinationARN string, repExistingObj, repDelMark, repDels, repMeta bool, tags string, priority int32, storageClass string) error {
// we will tolerate this call failing
cfg, err := minClient.getBucketReplication(ctx, bucketName)
if err != nil {
@@ -337,13 +337,18 @@ func addBucketReplicationItem(ctx context.Context, session *models.Principal, mi
repMetaStatus = "enable"
}
existingRepStatus := "disable"
if repExistingObj {
existingRepStatus = "enable"
}
opts := replication.Options{
Priority: fmt.Sprintf("%d", maxPrio),
RuleStatus: "enable",
DestBucket: destinationARN,
Op: replication.AddOption,
TagString: tags,
ExistingObjectReplicate: "enable", // enabled by default
ExistingObjectReplicate: existingRepStatus,
ReplicateDeleteMarkers: repDelMarkStatus,
ReplicateDeletes: repDelsStatus,
ReplicaSync: repMetaStatus,
@@ -459,6 +464,7 @@ func setMultiBucketReplication(ctx context.Context, session *models.Principal, c
sourceBucket,
params.Body.Prefix,
arn,
params.Body.ReplicateExistingObjects,
params.Body.ReplicateDeleteMarkers,
params.Body.ReplicateDeletes,
params.Body.ReplicateMetadata,
@@ -796,7 +802,6 @@ func updateBucketReplicationResponse(session *models.Principal, params bucketApi
params.Body.Tags,
params.Body.Priority,
params.Body.StorageClass)
if err != nil {
return ErrorWithContext(ctx, err)
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -27,9 +27,9 @@ import (
"github.com/minio/console/pkg/utils"
"github.com/go-openapi/swag"
"github.com/minio/console/api/operations"
bucketApi "github.com/minio/console/api/operations/bucket"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
bucketApi "github.com/minio/console/restapi/operations/bucket"
"github.com/minio/madmin-go/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@@ -299,7 +299,7 @@ func (suite *RemoteBucketsTestSuite) initListExternalBucketsRequest() (params bu
func (suite *RemoteBucketsTestSuite) TestListExternalBucketsWithError() {
ctx := context.Background()
minioAccountInfoMock = func(ctx context.Context) (madmin.AccountInfo, error) {
minioAccountInfoMock = func(_ context.Context) (madmin.AccountInfo, error) {
return madmin.AccountInfo{}, errors.New("error")
}
res, err := listExternalBuckets(ctx, &suite.adminClient)
@@ -309,7 +309,7 @@ func (suite *RemoteBucketsTestSuite) TestListExternalBucketsWithError() {
func (suite *RemoteBucketsTestSuite) TestListExternalBucketsWithoutError() {
ctx := context.Background()
minioAccountInfoMock = func(ctx context.Context) (madmin.AccountInfo, error) {
minioAccountInfoMock = func(_ context.Context) (madmin.AccountInfo, error) {
return madmin.AccountInfo{
Buckets: []madmin.BucketAccessInfo{},
}, nil

View File

@@ -14,15 +14,15 @@
// 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 restapi
package api
import (
"context"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
siteRepApi "github.com/minio/console/api/operations/site_replication"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
siteRepApi "github.com/minio/console/restapi/operations/site_replication"
"github.com/minio/madmin-go/v3"
)

View File

@@ -14,17 +14,17 @@
// 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 restapi
package api
import (
"context"
"time"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
svcApi "github.com/minio/console/restapi/operations/service"
svcApi "github.com/minio/console/api/operations/service"
)
func registerServiceHandlers(api *operations.ConsoleAPI) {

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -32,10 +32,10 @@ func TestServiceRestart(t *testing.T) {
function := "serviceRestart()"
// Test-1 : serviceRestart() restart services no errors
// mock function response from listGroups()
minioServiceRestartMock = func(ctx context.Context) error {
minioServiceRestartMock = func(_ context.Context) error {
return nil
}
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{}, nil
}
if err := serviceRestart(ctx, adminClient); err != nil {
@@ -44,10 +44,10 @@ func TestServiceRestart(t *testing.T) {
// Test-2 : serviceRestart() returns errors on client.serviceRestart call
// and see that the errors is handled correctly and returned
minioServiceRestartMock = func(ctx context.Context) error {
minioServiceRestartMock = func(_ context.Context) error {
return errors.New("error")
}
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{}, nil
}
if err := serviceRestart(ctx, adminClient); assert.Error(err) {
@@ -56,10 +56,10 @@ func TestServiceRestart(t *testing.T) {
// Test-3 : serviceRestart() returns errors on client.serverInfo() call
// and see that the errors is handled correctly and returned
minioServiceRestartMock = func(ctx context.Context) error {
minioServiceRestartMock = func(_ context.Context) error {
return nil
}
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{}, errors.New("error on server info")
}
if err := serviceRestart(ctx, adminClient); assert.Error(err) {

View File

@@ -14,15 +14,16 @@
// 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 restapi
package api
import (
"context"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
siteRepApi "github.com/minio/console/api/operations/site_replication"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
siteRepApi "github.com/minio/console/restapi/operations/site_replication"
"github.com/minio/madmin-go/v3"
)
@@ -162,7 +163,13 @@ func addSiteReplication(ctx context.Context, client MinioAdmin, params *siteRepA
rSites = append(rSites, *pInfo)
}
}
cc, err := client.addSiteReplicationInfo(ctx, rSites)
qs := runtime.Values(params.HTTPRequest.URL.Query())
_, qhkReplicateILMExpiry, _ := qs.GetOK("replicate-ilm-expiry")
var opts madmin.SRAddOptions
if qhkReplicateILMExpiry {
opts.ReplicateILMExpiry = true
}
cc, err := client.addSiteReplicationInfo(ctx, rSites, opts)
if err != nil {
return nil, err
}
@@ -183,7 +190,17 @@ func editSiteReplication(ctx context.Context, client MinioAdmin, params *siteRep
Name: params.Body.Name, // does not get updated.
DeploymentID: params.Body.DeploymentID, // readonly
}
eRes, err := client.editSiteReplicationInfo(ctx, *peerSiteInfo)
qs := runtime.Values(params.HTTPRequest.URL.Query())
_, qhkDisableILMExpiryReplication, _ := qs.GetOK("disable-ilm-expiry-replication")
_, qhkEnableILMExpiryReplication, _ := qs.GetOK("enable-ilm-expiry-replication")
var opts madmin.SREditOptions
if qhkDisableILMExpiryReplication {
opts.DisableILMExpiryReplication = true
}
if qhkEnableILMExpiryReplication {
opts.EnableILMExpiryReplication = true
}
eRes, err := client.editSiteReplicationInfo(ctx, *peerSiteInfo, opts)
if err != nil {
return nil, err
}

View File

@@ -16,7 +16,7 @@
// These tests are for AdminAPI Tag based on swagger-console.yml
package restapi
package api
import (
"context"
@@ -72,7 +72,7 @@ func TestGetSiteReplicationInfo(t *testing.T) {
ServiceAccountAccessKey: "test-key",
}
getSiteReplicationInfo = func(ctx context.Context) (info *madmin.SiteReplicationInfo, err error) {
getSiteReplicationInfo = func(_ context.Context) (info *madmin.SiteReplicationInfo, err error) {
return &retValueMock, nil
}
@@ -104,7 +104,7 @@ func TestAddSiteReplicationInfo(t *testing.T) {
InitialSyncErrorMessage: "",
}
addSiteReplicationInfo = func(ctx context.Context, sites []madmin.PeerSite) (res *madmin.ReplicateAddStatus, err error) {
addSiteReplicationInfo = func(_ context.Context, _ []madmin.PeerSite) (res *madmin.ReplicateAddStatus, err error) {
return retValueMock, nil
}
@@ -123,7 +123,7 @@ func TestAddSiteReplicationInfo(t *testing.T) {
},
}
srInfo, err := adminClient.addSiteReplicationInfo(ctx, sites)
srInfo, err := adminClient.addSiteReplicationInfo(ctx, sites, madmin.SRAddOptions{})
assert.Nil(err)
assert.Equal(expValueMock, srInfo, fmt.Sprintf("Failed on %s: length of lists is not the same", function))
}
@@ -149,7 +149,7 @@ func TestEditSiteReplicationInfo(t *testing.T) {
ErrDetail: "",
}
editSiteReplicationInfo = func(ctx context.Context, site madmin.PeerInfo) (res *madmin.ReplicateEditStatus, err error) {
editSiteReplicationInfo = func(_ context.Context, _ madmin.PeerInfo) (res *madmin.ReplicateEditStatus, err error) {
return retValueMock, nil
}
@@ -159,7 +159,7 @@ func TestEditSiteReplicationInfo(t *testing.T) {
DeploymentID: "12345",
}
srInfo, err := adminClient.editSiteReplicationInfo(ctx, site)
srInfo, err := adminClient.editSiteReplicationInfo(ctx, site, madmin.SREditOptions{})
assert.Nil(err)
assert.Equal(expValueMock, srInfo, fmt.Sprintf("Failed on %s: length of lists is not the same", function))
}
@@ -183,7 +183,7 @@ func TestDeleteSiteReplicationInfo(t *testing.T) {
ErrDetail: "",
}
deleteSiteReplicationInfoMock = func(ctx context.Context, removeReq madmin.SRRemoveReq) (res *madmin.ReplicateRemoveStatus, err error) {
deleteSiteReplicationInfoMock = func(_ context.Context, _ madmin.SRRemoveReq) (res *madmin.ReplicateRemoveStatus, err error) {
return retValueMock, nil
}
@@ -236,7 +236,7 @@ func TestSiteReplicationStatus(t *testing.T) {
GroupStats: nil,
}
getSiteReplicationStatus = func(ctx context.Context, params madmin.SRStatusOptions) (info *madmin.SRStatusInfo, err error) {
getSiteReplicationStatus = func(_ context.Context, _ madmin.SRStatusOptions) (info *madmin.SRStatusInfo, err error) {
return &retValueMock, nil
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
import (
"context"
@@ -30,10 +30,10 @@ import (
xhttp "github.com/minio/console/pkg/http"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
subnetApi "github.com/minio/console/api/operations/subnet"
"github.com/minio/console/models"
"github.com/minio/console/pkg/subnet"
"github.com/minio/console/restapi/operations"
subnetApi "github.com/minio/console/restapi/operations/subnet"
"github.com/minio/madmin-go/v3"
)
@@ -96,7 +96,7 @@ func SubnetRegisterWithAPIKey(ctx context.Context, minioClient MinioAdmin, apiKe
return false, err
}
clientIP := utils.ClientIPFromContext(ctx)
registerResult, err := subnet.Register(GetConsoleHTTPClient("", clientIP), serverInfo, apiKey, "", "")
registerResult, err := subnet.Register(GetConsoleHTTPClient(clientIP), serverInfo, apiKey, "", "")
if err != nil {
return false, err
}
@@ -199,7 +199,6 @@ func SubnetLoginWithMFA(client xhttp.ClientI, username, mfaToken, otp string) (*
// GetSubnetHTTPClient will return a client with proxy if configured, otherwise will return the default console http client
func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*xhttp.Client, error) {
clientIP := utils.ClientIPFromContext(ctx)
subnetHTTPClient := GetConsoleHTTPClient("", clientIP)
subnetKey, err := GetSubnetKeyFromMinIOConfig(ctx, minioClient)
if err != nil {
return nil, err
@@ -209,18 +208,24 @@ func GetSubnetHTTPClient(ctx context.Context, minioClient MinioAdmin) (*xhttp.Cl
if subnetKey.Proxy != "" {
proxy = subnetKey.Proxy
}
tr := GlobalTransport.Clone()
if proxy != "" {
subnetProxyURL, err := url.Parse(proxy)
u, err := url.Parse(proxy)
if err != nil {
return nil, err
}
subnetHTTPClient.Transport.(*ConsoleTransport).Transport.Proxy = http.ProxyURL(subnetProxyURL)
tr.Proxy = http.ProxyURL(u)
}
clientI := &xhttp.Client{
Client: subnetHTTPClient,
}
return clientI, nil
return &xhttp.Client{
Client: &http.Client{
Transport: &ConsoleTransport{
Transport: tr,
ClientIP: clientIP,
},
},
}, nil
}
func GetSubnetLoginWithMFAResponse(session *models.Principal, params subnetApi.SubnetLoginMFAParams) (*models.SubnetLoginResponse, *CodedAPIError) {
@@ -322,7 +327,7 @@ func GetSubnetInfoResponse(session *models.Principal, params subnetApi.SubnetInf
defer cancel()
clientIP := utils.ClientIPFromContext(ctx)
client := &xhttp.Client{
Client: GetConsoleHTTPClient("", clientIP),
Client: GetConsoleHTTPClient(clientIP),
}
// license gets seeded to us by MinIO
seededLicense := os.Getenv(EnvSubnetLicense)
@@ -356,7 +361,7 @@ func GetSubnetInfoResponse(session *models.Principal, params subnetApi.SubnetInf
return nil, ErrorWithContext(ctx, ErrSubnetLicenseNotFound)
}
licenseInfo, err := subnet.ParseLicense(client, seededLicense)
licenseInfo, err := getLicenseInfo(*client.Client, seededLicense)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -24,9 +24,9 @@ import (
"os"
"testing"
"github.com/minio/console/api/operations"
subnetApi "github.com/minio/console/api/operations/subnet"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
subnetApi "github.com/minio/console/restapi/operations/subnet"
"github.com/minio/madmin-go/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
@@ -44,10 +44,10 @@ type AdminSubnetTestSuite struct {
func (suite *AdminSubnetTestSuite) SetupSuite() {
suite.assert = assert.New(suite.T())
suite.adminClient = AdminClientMock{}
minioGetConfigKVMock = func(key string) ([]byte, error) {
minioGetConfigKVMock = func(_ string) ([]byte, error) {
return []byte("subnet license=mock api_key=mock proxy=http://mock.com"), nil
}
MinioServerInfoMock = func(ctx context.Context) (madmin.InfoMessage, error) {
MinioServerInfoMock = func(_ context.Context) (madmin.InfoMessage, error) {
return madmin.InfoMessage{Servers: []madmin.ServerProperties{{}}}, nil
}
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -23,9 +23,9 @@ import (
"github.com/dustin/go-humanize"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
tieringApi "github.com/minio/console/api/operations/tiering"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
tieringApi "github.com/minio/console/restapi/operations/tiering"
"github.com/minio/madmin-go/v3"
)

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -22,8 +22,8 @@ import (
"fmt"
"testing"
tieringApi "github.com/minio/console/api/operations/tiering"
"github.com/minio/console/models"
tieringApi "github.com/minio/console/restapi/operations/tiering"
"github.com/minio/madmin-go/v3"
"github.com/stretchr/testify/assert"
)
@@ -89,11 +89,11 @@ func TestGetTiers(t *testing.T) {
},
}
minioListTiersMock = func(ctx context.Context) ([]*madmin.TierConfig, error) {
minioListTiersMock = func(_ context.Context) ([]*madmin.TierConfig, error) {
return returnListMock, nil
}
minioTierStatsMock = func(ctx context.Context) ([]madmin.TierInfo, error) {
minioTierStatsMock = func(_ context.Context) ([]madmin.TierInfo, error) {
return returnStatsMock, nil
}
@@ -138,7 +138,7 @@ func TestGetTiers(t *testing.T) {
// Test-2 : getBucketLifecycle() list is empty
returnListMockT2 := []*madmin.TierConfig{}
minioListTiersMock = func(ctx context.Context) ([]*madmin.TierConfig, error) {
minioListTiersMock = func(_ context.Context) ([]*madmin.TierConfig, error) {
return returnListMockT2, nil
}
@@ -161,7 +161,7 @@ func TestAddTier(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Test-1: addTier() add new Tier
minioAddTiersMock = func(ctx context.Context, tier *madmin.TierConfig) error {
minioAddTiersMock = func(_ context.Context, _ *madmin.TierConfig) error {
return nil
}
@@ -185,7 +185,7 @@ func TestAddTier(t *testing.T) {
assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function))
// Test-2: addTier() error adding Tier
minioAddTiersMock = func(ctx context.Context, tier *madmin.TierConfig) error {
minioAddTiersMock = func(_ context.Context, _ *madmin.TierConfig) error {
return errors.New("error setting new tier")
}
@@ -203,7 +203,7 @@ func TestUpdateTierCreds(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Test-1: editTierCredentials() update Tier configuration
minioEditTiersMock = func(ctx context.Context, tierName string, creds madmin.TierCreds) error {
minioEditTiersMock = func(_ context.Context, _ string, _ madmin.TierCreds) error {
return nil
}
@@ -220,7 +220,7 @@ func TestUpdateTierCreds(t *testing.T) {
assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function))
// Test-2: editTierCredentials() update Tier configuration failure
minioEditTiersMock = func(ctx context.Context, tierName string, creds madmin.TierCreds) error {
minioEditTiersMock = func(_ context.Context, _ string, _ madmin.TierCreds) error {
return errors.New("error message")
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -41,7 +41,7 @@ func TestAdminTrace(t *testing.T) {
// Test-1: Serve Trace with no errors until trace finishes sending
// define mock function behavior for minio server Trace
minioServiceTraceMock = func(ctx context.Context, threshold int64, s3, internal, storage, os, errTrace bool) <-chan madmin.ServiceTraceInfo {
minioServiceTraceMock = func(_ context.Context, _ int64, _, _, _, _, _ bool) <-chan madmin.ServiceTraceInfo {
ch := make(chan madmin.ServiceTraceInfo)
// Only success, start a routine to start reading line by line.
go func(ch chan<- madmin.ServiceTraceInfo) {
@@ -59,7 +59,7 @@ func TestAdminTrace(t *testing.T) {
}
writesCount := 1
// mock connection WriteMessage() no error
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, data []byte) error {
// emulate that receiver gets the message written
var t shortTraceMsg
_ = json.Unmarshal(data, &t)
@@ -84,7 +84,7 @@ func TestAdminTrace(t *testing.T) {
}
// Test-2: if error happens while writing, return error
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, _ []byte) error {
return fmt.Errorf("error on write")
}
if err := startTraceInfo(ctx, mockWSConn, adminClient, TraceRequest{}); assert.Error(err) {
@@ -93,7 +93,7 @@ func TestAdminTrace(t *testing.T) {
// Test-3: error happens on serviceTrace Minio, trace should stop
// and error shall be returned.
minioServiceTraceMock = func(ctx context.Context, threshold int64, s3, internal, storage, os, errTrace bool) <-chan madmin.ServiceTraceInfo {
minioServiceTraceMock = func(_ context.Context, _ int64, _, _, _, _, _ bool) <-chan madmin.ServiceTraceInfo {
ch := make(chan madmin.ServiceTraceInfo)
// Only success, start a routine to start reading line by line.
go func(ch chan<- madmin.ServiceTraceInfo) {
@@ -110,7 +110,7 @@ func TestAdminTrace(t *testing.T) {
}(ch)
return ch
}
connWriteMessageMock = func(messageType int, data []byte) error {
connWriteMessageMock = func(_ int, _ []byte) error {
return nil
}
if err := startTraceInfo(ctx, mockWSConn, adminClient, TraceRequest{}); assert.Error(err) {

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -26,13 +26,13 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/api/operations"
accountApi "github.com/minio/console/api/operations/account"
bucketApi "github.com/minio/console/api/operations/bucket"
userApi "github.com/minio/console/api/operations/user"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
accountApi "github.com/minio/console/restapi/operations/account"
bucketApi "github.com/minio/console/restapi/operations/bucket"
userApi "github.com/minio/console/restapi/operations/user"
"github.com/minio/madmin-go/v3"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
)
// Policy evaluated constants

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"bytes"
@@ -25,7 +25,7 @@ import (
"testing"
"github.com/minio/madmin-go/v3"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
asrt "github.com/stretchr/testify/assert"
)
@@ -102,15 +102,15 @@ func TestAddUser(t *testing.T) {
}
// mock function response from addUser() return no error
minioAddUserMock = func(accessKey, secretKey string) error {
minioAddUserMock = func(_, _ string) error {
return nil
}
minioGetUserInfoMock = func(accessKey string) (madmin.UserInfo, error) {
minioGetUserInfoMock = func(_ string) (madmin.UserInfo, error) {
return *mockResponse, nil
}
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return nil
}
// Test-1: Add a user
@@ -135,7 +135,7 @@ func TestAddUser(t *testing.T) {
accessKey = "AB"
secretKey = "ABCDEFGHIABCDEFGHI"
// mock function response from addUser() return no error
minioAddUserMock = func(accessKey, secretKey string) error {
minioAddUserMock = func(_, _ string) error {
return errors.New("error")
}
@@ -150,7 +150,7 @@ func TestAddUser(t *testing.T) {
}
// Test-4: add groups function returns an error
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return errors.New("error")
}
@@ -175,7 +175,7 @@ func TestRemoveUser(t *testing.T) {
// Test-1: removeUser() delete a user
// mock function response from removeUser(accessKey)
minioRemoveUserMock = func(accessKey string) error {
minioRemoveUserMock = func(_ string) error {
return nil
}
@@ -185,7 +185,7 @@ func TestRemoveUser(t *testing.T) {
// Test-2: removeUser() make sure errors are handled correctly when error on DeleteUser()
// mock function response from removeUser(accessKey)
minioRemoveUserMock = func(accessKey string) error {
minioRemoveUserMock = func(_ string) error {
return errors.New("error")
}
@@ -220,11 +220,11 @@ func TestUserGroups(t *testing.T) {
// Test-1: updateUserGroups() updates the groups for a user
// mock function response from updateUserGroups(accessKey, groupsToAssign)
minioGetUserInfoMock = func(accessKey string) (madmin.UserInfo, error) {
minioGetUserInfoMock = func(_ string) (madmin.UserInfo, error) {
return *mockResponse, nil
}
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return nil
}
@@ -235,7 +235,7 @@ func TestUserGroups(t *testing.T) {
// Test-2: updateUserGroups() make sure errors are handled correctly when error on UpdateGroupMembersMock()
// mock function response from removeUser(accessKey)
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return errors.New("error")
}
@@ -244,11 +244,11 @@ func TestUserGroups(t *testing.T) {
}
// Test-3: updateUserGroups() make sure we return the correct error when getUserInfo returns error
minioGetUserInfoMock = func(accessKey string) (madmin.UserInfo, error) {
minioGetUserInfoMock = func(_ string) (madmin.UserInfo, error) {
return *mockEmptyResponse, errors.New("error getting user ")
}
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return nil
}
@@ -279,7 +279,7 @@ func TestGetUserInfo(t *testing.T) {
}
// mock function response from getUserInfo()
minioGetUserInfoMock = func(username string) (madmin.UserInfo, error) {
minioGetUserInfoMock = func(_ string) (madmin.UserInfo, error) {
return *mockResponse, nil
}
function := "getUserInfo()"
@@ -294,7 +294,7 @@ func TestGetUserInfo(t *testing.T) {
assert.Equal(mockResponse.Status, info.Status)
// Test-2 : getUserInfo() Return error and see that the error is handled correctly and returned
minioGetUserInfoMock = func(username string) (madmin.UserInfo, error) {
minioGetUserInfoMock = func(_ string) (madmin.UserInfo, error) {
return *emptyMockResponse, errors.New("error")
}
_, err = getUserInfo(ctx, adminClient, userName)
@@ -313,7 +313,7 @@ func TestSetUserStatus(t *testing.T) {
// Test-1: setUserStatus() update valid disabled status
expectedStatus := "disabled"
minioSetUserStatusMock = func(accessKey string, status madmin.AccountStatus) error {
minioSetUserStatusMock = func(_ string, _ madmin.AccountStatus) error {
return nil
}
if err := setUserStatus(ctx, adminClient, userName, expectedStatus); err != nil {
@@ -321,7 +321,7 @@ func TestSetUserStatus(t *testing.T) {
}
// Test-2: setUserStatus() update valid enabled status
expectedStatus = "enabled"
minioSetUserStatusMock = func(accessKey string, status madmin.AccountStatus) error {
minioSetUserStatusMock = func(_ string, _ madmin.AccountStatus) error {
return nil
}
if err := setUserStatus(ctx, adminClient, userName, expectedStatus); err != nil {
@@ -329,7 +329,7 @@ func TestSetUserStatus(t *testing.T) {
}
// Test-3: setUserStatus() update invalid status, should send error
expectedStatus = "invalid"
minioSetUserStatusMock = func(accessKey string, status madmin.AccountStatus) error {
minioSetUserStatusMock = func(_ string, _ madmin.AccountStatus) error {
return nil
}
if err := setUserStatus(ctx, adminClient, userName, expectedStatus); assert.Error(err) {
@@ -337,7 +337,7 @@ func TestSetUserStatus(t *testing.T) {
}
// Test-4: setUserStatus() handler error correctly
expectedStatus = "enabled"
minioSetUserStatusMock = func(accessKey string, status madmin.AccountStatus) error {
minioSetUserStatusMock = func(_ string, _ madmin.AccountStatus) error {
return errors.New("error")
}
if err := setUserStatus(ctx, adminClient, userName, expectedStatus); assert.Error(err) {
@@ -358,7 +358,7 @@ func TestUserGroupsBulk(t *testing.T) {
// Test-1: addUsersListToGroups() updates the groups for a users list
// mock function response from updateUserGroups(accessKey, groupsToAssign)
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return nil
}
@@ -368,7 +368,7 @@ func TestUserGroupsBulk(t *testing.T) {
// Test-2: addUsersListToGroups() make sure errors are handled correctly when error on updateGroupMembers()
// mock function response from removeUser(accessKey)
minioUpdateGroupMembersMock = func(remove madmin.GroupAddRemove) error {
minioUpdateGroupMembersMock = func(_ madmin.GroupAddRemove) error {
return errors.New("error")
}
@@ -527,7 +527,7 @@ func TestListUsersWithAccessToBucket(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
got, _ := listUsersWithAccessToBucket(ctx, adminClient, tt.args.bucket)
assert.Equal(got, tt.want)
})

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"bytes"
@@ -24,15 +24,18 @@ import (
"net"
"net/http"
"net/url"
"regexp"
"strings"
"time"
"github.com/minio/console/pkg"
"github.com/minio/console/pkg/utils"
"github.com/minio/console/models"
"github.com/minio/madmin-go/v3"
"github.com/minio/minio-go/v7/pkg/credentials"
iampolicy "github.com/minio/pkg/v2/policy"
iampolicy "github.com/minio/pkg/v3/policy"
)
const globalAppName = "MinIO Console"
@@ -70,7 +73,7 @@ type MinioAdmin interface {
heal(ctx context.Context, bucket, prefix string, healOpts madmin.HealOpts, clientToken string,
forceStart, forceStop bool) (healStart madmin.HealStartSuccess, healTaskStatus madmin.HealTaskStatus, err error)
// Service Accounts
addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (madmin.Credentials, error)
addServiceAccount(ctx context.Context, policy string, user string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (madmin.Credentials, error)
listServiceAccounts(ctx context.Context, user string) (madmin.ListServiceAccountsResp, error)
deleteServiceAccount(ctx context.Context, serviceAccount string) error
infoServiceAccount(ctx context.Context, serviceAccount string) (madmin.InfoServiceAccountResp, error)
@@ -82,7 +85,7 @@ type MinioAdmin interface {
addRemoteBucket(ctx context.Context, bucket string, target *madmin.BucketTarget) (string, error)
// Account password management
changePassword(ctx context.Context, accessKey, secretKey string) error
serverHealthInfo(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) (interface{}, string, error)
serverHealthInfo(ctx context.Context, deadline time.Duration) (interface{}, string, error)
// List Tiers
listTiers(ctx context.Context) ([]*madmin.TierConfig, error)
// Tier Info
@@ -97,8 +100,8 @@ type MinioAdmin interface {
speedtest(ctx context.Context, opts madmin.SpeedtestOpts) (chan madmin.SpeedTestResult, error)
// Site Relication
getSiteReplicationInfo(ctx context.Context) (*madmin.SiteReplicationInfo, error)
addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite) (*madmin.ReplicateAddStatus, error)
editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo) (*madmin.ReplicateEditStatus, error)
addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite, opts madmin.SRAddOptions) (*madmin.ReplicateAddStatus, error)
editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo, opts madmin.SREditOptions) (*madmin.ReplicateEditStatus, error)
deleteSiteReplicationInfo(ctx context.Context, removeReq madmin.SRRemoveReq) (*madmin.ReplicateRemoveStatus, error)
// Replication status
@@ -211,11 +214,11 @@ func (ac AdminClient) listPolicies(ctx context.Context) (map[string]*iampolicy.P
// implements madmin.ListCannedPolicies()
func (ac AdminClient) getPolicy(ctx context.Context, name string) (*iampolicy.Policy, error) {
praw, err := ac.Client.InfoCannedPolicy(ctx, name)
info, err := ac.Client.InfoCannedPolicyV2(ctx, name)
if err != nil {
return nil, err
}
return iampolicy.ParseConfig(bytes.NewReader(praw))
return iampolicy.ParseConfig(bytes.NewReader(info.Policy))
}
// implements madmin.RemoveCannedPolicy()
@@ -234,6 +237,7 @@ func (ac AdminClient) addPolicy(ctx context.Context, name string, policy *iampol
// implements madmin.SetPolicy()
func (ac AdminClient) setPolicy(ctx context.Context, policyName, entityName string, isGroup bool) error {
// nolint:staticcheck // ignore SA1019
return ac.Client.SetPolicy(ctx, policyName, entityName, isGroup)
}
@@ -305,13 +309,9 @@ func (ac AdminClient) getLogs(ctx context.Context, node string, lineCnt int, log
}
// implements madmin.AddServiceAccount()
func (ac AdminClient) addServiceAccount(ctx context.Context, policy *iampolicy.Policy, user string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (madmin.Credentials, error) {
buf, err := json.Marshal(policy)
if err != nil {
return madmin.Credentials{}, err
}
func (ac AdminClient) addServiceAccount(ctx context.Context, policy string, user string, accessKey string, secretKey string, name string, description string, expiry *time.Time, comment string) (madmin.Credentials, error) {
return ac.Client.AddServiceAccount(ctx, madmin.AddServiceAccountReq{
Policy: buf,
Policy: []byte(policy),
TargetUser: user,
AccessKey: accessKey,
SecretKey: secretKey,
@@ -389,13 +389,15 @@ func (ac AdminClient) getBucketQuota(ctx context.Context, bucket string) (madmin
}
// serverHealthInfo implements mc.ServerHealthInfo - Connect to a minio server and call Health Info Management API
func (ac AdminClient) serverHealthInfo(ctx context.Context, healthDataTypes []madmin.HealthDataType, deadline time.Duration) (interface{}, string, error) {
func (ac AdminClient) serverHealthInfo(ctx context.Context, deadline time.Duration) (interface{}, string, error) {
info := madmin.HealthInfo{}
var healthInfo interface{}
var version string
var tryCount int
for info.Version == "" && tryCount < 10 {
resp, version, err := ac.Client.ServerHealthInfo(ctx, healthDataTypes, deadline, "")
var resp *http.Response
var err error
resp, version, err = ac.Client.ServerHealthInfo(ctx, madmin.HealthDataTypesList, deadline, "")
if err != nil {
return nil, version, err
}
@@ -407,7 +409,6 @@ func (ac AdminClient) serverHealthInfo(ctx context.Context, healthDataTypes []ma
}
tryCount++
time.Sleep(2 * time.Second)
}
if info.Version == "" {
return nil, "", ErrHealthReportFail
@@ -453,6 +454,7 @@ func NewMinioAdminClient(ctx context.Context, sessionClaims *models.Principal) (
if err != nil {
return nil, err
}
adminClient.SetAppInfo(globalAppName, pkg.Version)
return adminClient, nil
}
@@ -468,7 +470,8 @@ func newAdminFromClaims(claims *models.Principal, clientIP string) (*madmin.Admi
if err != nil {
return nil, err
}
adminClient.SetCustomTransport(GetConsoleHTTPClient(getMinIOServer(), clientIP).Transport)
adminClient.SetAppInfo(globalAppName, pkg.Version)
adminClient.SetCustomTransport(PrepareSTSClientTransport(clientIP))
return adminClient, nil
}
@@ -481,14 +484,14 @@ func newAdminFromCreds(accessKey, secretKey, endpoint string, tlsEnabled bool) (
if err != nil {
return nil, err
}
minioClient.SetAppInfo(globalAppName, pkg.Version)
return minioClient, nil
}
// isLocalAddress returns true if the url contains an IPv4/IPv6 hostname
// that points to the local machine - FQDN are not supported
func isLocalIPEndpoint(addr string) bool {
u, err := url.Parse(addr)
func isLocalIPEndpoint(endpoint string) bool {
u, err := url.Parse(endpoint)
if err != nil {
return false
}
@@ -501,6 +504,9 @@ func isLocalIPAddress(ipAddr string) bool {
if ipAddr == "" {
return false
}
if ipAddr == "localhost" {
return true
}
ip := net.ParseIP(ipAddr)
return ip != nil && ip.IsLoopback()
}
@@ -508,43 +514,75 @@ func isLocalIPAddress(ipAddr string) bool {
// GetConsoleHTTPClient caches different http clients depending on the target endpoint while taking
// in consideration CA certs stored in ${HOME}/.console/certs/CAs and ${HOME}/.minio/certs/CAs
// If the target endpoint points to a loopback device, skip the TLS verification.
func GetConsoleHTTPClient(address string, clientIP string) *http.Client {
u, err := url.Parse(address)
if err == nil {
address = u.Hostname()
}
client := PrepareConsoleHTTPClient(isLocalIPAddress(address), clientIP)
return client
func GetConsoleHTTPClient(clientIP string) *http.Client {
return PrepareConsoleHTTPClient(clientIP)
}
func getClientIP(r *http.Request) string {
// Try to get the IP address from the X-Real-IP header
// If the X-Real-IP header is not present, then it will return an empty string
xRealIP := r.Header.Get("X-Real-IP")
if xRealIP != "" {
return xRealIP
}
var (
// De-facto standard header keys.
xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
xRealIP = http.CanonicalHeaderKey("X-Real-IP")
)
// Try to get the IP address from the X-Forwarded-For header
// If the X-Forwarded-For header is not present, then it will return an empty string
xForwardedFor := r.Header.Get("X-Forwarded-For")
if xForwardedFor != "" {
// X-Forwarded-For can contain multiple addresses, we return the first one
split := strings.Split(xForwardedFor, ",")
if len(split) > 0 {
return strings.TrimSpace(split[0])
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=)([^(;|,| )]+)(.*)`)
)
// getSourceIPFromHeaders retrieves the IP from the X-Forwarded-For, X-Real-IP
// and RFC7239 Forwarded headers (in that order)
func getSourceIPFromHeaders(r *http.Request) string {
var addr string
if fwd := r.Header.Get(xForwardedFor); fwd != "" {
// Only grab the first (client) address. Note that '192.168.0.1,
// 10.1.1.1' is a valid key for X-Forwarded-For where addresses after
// the first may represent forwarding proxies earlier in the chain.
s := strings.Index(fwd, ", ")
if s == -1 {
s = len(fwd)
}
addr = fwd[:s]
} else if fwd := r.Header.Get(xRealIP); fwd != "" {
// X-Real-IP should only contain one IP address (the client making the
// request).
addr = fwd
} else if fwd := r.Header.Get(forwarded); fwd != "" {
// match should contain at least two elements if the protocol was
// specified in the Forwarded header. The first element will always be
// the 'for=' capture, which we ignore. In the case of multiple IP
// addresses (for=8.8.8.8, 8.8.4.4, 172.16.1.20 is valid) we only
// extract the first, which should be the client IP.
if match := forRegex.FindStringSubmatch(fwd); len(match) > 1 {
// IPv6 addresses in Forwarded headers are quoted-strings. We strip
// these quotes.
addr = strings.Trim(match[1], `"`)
}
}
// If neither header is present (or they were empty), then fall back to the connection's remote address
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
// In case there's an error, return an empty string
return ""
return addr
}
// getClientIP retrieves the IP from the request headers
// and falls back to r.RemoteAddr when necessary.
// however returns without bracketing.
func getClientIP(r *http.Request) string {
addr := getSourceIPFromHeaders(r)
if addr == "" {
addr = r.RemoteAddr
}
return ip
// Default to remote address if headers not set.
raddr, _, _ := net.SplitHostPort(addr)
if raddr == "" {
return addr
}
return raddr
}
func (ac AdminClient) speedtest(ctx context.Context, opts madmin.SpeedtestOpts) (chan madmin.SpeedTestResult, error) {
@@ -565,8 +603,8 @@ func (ac AdminClient) getSiteReplicationInfo(ctx context.Context) (*madmin.SiteR
}, nil
}
func (ac AdminClient) addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite) (*madmin.ReplicateAddStatus, error) {
res, err := ac.Client.SiteReplicationAdd(ctx, sites, madmin.SRAddOptions{})
func (ac AdminClient) addSiteReplicationInfo(ctx context.Context, sites []madmin.PeerSite, opts madmin.SRAddOptions) (*madmin.ReplicateAddStatus, error) {
res, err := ac.Client.SiteReplicationAdd(ctx, sites, opts)
if err != nil {
return nil, err
}
@@ -579,8 +617,8 @@ func (ac AdminClient) addSiteReplicationInfo(ctx context.Context, sites []madmin
}, nil
}
func (ac AdminClient) editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo) (*madmin.ReplicateEditStatus, error) {
res, err := ac.Client.SiteReplicationEdit(ctx, site, madmin.SREditOptions{})
func (ac AdminClient) editSiteReplicationInfo(ctx context.Context, site madmin.PeerInfo, opts madmin.SREditOptions) (*madmin.ReplicateEditStatus, error) {
res, err := ac.Client.SiteReplicationEdit(ctx, site, opts)
if err != nil {
return nil, err
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -27,7 +27,7 @@ import (
"github.com/minio/minio-go/v7/pkg/replication"
"github.com/minio/minio-go/v7/pkg/sse"
xnet "github.com/minio/pkg/v2/net"
xnet "github.com/minio/pkg/v3/net"
"github.com/minio/console/models"
"github.com/minio/console/pkg"
@@ -278,7 +278,8 @@ func (c mcClient) list(ctx context.Context, opts mc.ListOptions) <-chan *mc.Clie
}
func (c mcClient) get(ctx context.Context, opts mc.GetOptions) (io.ReadCloser, *probe.Error) {
return c.client.Get(ctx, opts)
rd, _, err := c.client.Get(ctx, opts)
return rd, err
}
func (c mcClient) shareDownload(ctx context.Context, versionID string, expires time.Duration) (string, *probe.Error) {
@@ -340,7 +341,7 @@ func stsCredentials(minioURL, accessKey, secretKey, location, clientIP string) (
DurationSeconds: int(xjwt.GetConsoleSTSDuration().Seconds()),
}
stsAssumeRole := &credentials.STSAssumeRole{
Client: GetConsoleHTTPClient(minioURL, clientIP),
Client: GetConsoleHTTPClient(clientIP),
STSEndpoint: minioURL,
Options: opts,
}
@@ -356,7 +357,7 @@ func NewConsoleCredentials(accessKey, secretKey, location, clientIP string) (*cr
// LDAP authentication for Console
case ldap.GetLDAPEnabled():
{
creds, err := auth.GetCredentialsFromLDAP(GetConsoleHTTPClient(minioURL, clientIP), minioURL, accessKey, secretKey)
creds, err := auth.GetCredentialsFromLDAP(GetConsoleHTTPClient(clientIP), minioURL, accessKey, secretKey)
if err != nil {
return nil, err
}
@@ -413,7 +414,7 @@ func newMinioClient(claims *models.Principal, clientIP string) (*minio.Client, e
minioClient, err := minio.New(endpoint, &minio.Options{
Creds: creds,
Secure: secure,
Transport: GetConsoleHTTPClient(getMinIOServer(), clientIP).Transport,
Transport: GetConsoleHTTPClient(clientIP).Transport,
})
if err != nil {
return nil, err
@@ -425,10 +426,9 @@ func newMinioClient(claims *models.Principal, clientIP string) (*minio.Client, e
// computeObjectURLWithoutEncode returns a MinIO url containing the object filename without encoding
func computeObjectURLWithoutEncode(bucketName, prefix string) (string, error) {
endpoint := getMinIOServer()
u, err := xnet.ParseHTTPURL(endpoint)
u, err := xnet.ParseHTTPURL(getMinIOServer())
if err != nil {
return "", fmt.Errorf("the provided endpoint is invalid")
return "", fmt.Errorf("the provided endpoint: '%s' is invalid", getMinIOServer())
}
var p string
if strings.TrimSpace(bucketName) != "" {
@@ -437,7 +437,7 @@ func computeObjectURLWithoutEncode(bucketName, prefix string) (string, error) {
if strings.TrimSpace(prefix) != "" {
p = pathJoinFinalSlash(p, prefix)
}
return fmt.Sprintf("%s://%s/%s", u.Scheme, u.Host, p), nil
return u.String() + "/" + p, nil
}
// newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket
@@ -478,22 +478,18 @@ func pathJoinFinalSlash(elem ...string) string {
func newS3Config(endpoint, accessKey, secretKey, sessionToken string, clientIP string) *mc.Config {
// We have a valid alias and hostConfig. We populate the/
// consoleCredentials from the match found in the config file.
s3Config := new(mc.Config)
s3Config.AppName = globalAppName
s3Config.AppVersion = pkg.Version
s3Config.Debug = false
s3Config.HostURL = endpoint
s3Config.AccessKey = accessKey
s3Config.SecretKey = secretKey
s3Config.SessionToken = sessionToken
s3Config.Signature = "S3v4"
insecure := isLocalIPEndpoint(endpoint)
s3Config.Insecure = insecure
s3Config.Transport = PrepareSTSClientTransport(insecure, clientIP).Transport
return s3Config
return &mc.Config{
HostURL: endpoint,
AccessKey: accessKey,
SecretKey: secretKey,
SessionToken: sessionToken,
Signature: "S3v4",
AppName: globalAppName,
AppVersion: pkg.Version,
Insecure: isLocalIPEndpoint(endpoint),
Transport: &ConsoleTransport{
ClientIP: clientIP,
Transport: GlobalTransport,
},
}
}

View File

@@ -1,5 +1,5 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
// Copyright (c) 2024 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
@@ -14,7 +14,7 @@
// 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 restapi
package api
import "testing"
@@ -76,14 +76,15 @@ func Test_computeObjectURLWithoutEncode(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
got, err := computeObjectURLWithoutEncode(tt.args.bucketName, tt.args.prefix)
if (err != nil) != tt.wantErr {
t.Errorf("computeObjectURLWithoutEncode() errors = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("computeObjectURLWithoutEncode() got = %v, want %v", got, tt.want)
if err == nil {
if got != tt.want {
t.Errorf("computeObjectURLWithoutEncode() got = %v, want %v", got, tt.want)
}
}
})
}

View File

@@ -14,18 +14,21 @@
// 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 restapi
package api
import (
"crypto/tls"
"crypto/x509"
"net"
"net/http"
"strconv"
"strings"
"time"
"github.com/minio/console/pkg/auth/idp/oauth2"
xcerts "github.com/minio/pkg/v2/certs"
"github.com/minio/pkg/v2/env"
xnet "github.com/minio/pkg/v2/net"
xcerts "github.com/minio/pkg/v3/certs"
"github.com/minio/pkg/v3/env"
xnet "github.com/minio/pkg/v3/net"
)
var (
@@ -54,6 +57,31 @@ var (
GlobalPublicCerts []*x509.Certificate
// GlobalTLSCertsManager custom TLS Manager for SNI support
GlobalTLSCertsManager *xcerts.Manager
// GlobalTransport is common transport used for all HTTP calls, this is set via
// MinIO server to be the correct transport, however we still define some defaults
// here just in case.
GlobalTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 15 * time.Second,
}).DialContext,
MaxIdleConns: 1024,
MaxIdleConnsPerHost: 1024,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 10 * time.Second,
DisableCompression: true, // Set to avoid auto-decompression
TLSClientConfig: &tls.Config{
// Can't use SSLv3 because of POODLE and BEAST
// Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher
// Can't use TLSv1.1 because of RC4 cipher usage
MinVersion: tls.VersionTLS12,
// Console runs in the same pod/node as MinIO this is acceptable.
InsecureSkipVerify: true,
RootCAs: GlobalRootCAs,
},
}
)
// MinIOConfig represents application configuration passed in from the MinIO
@@ -213,11 +241,6 @@ func GetSecureForceSTSHeader() bool {
return strings.ToLower(env.Get(ConsoleSecureForceSTSHeader, "off")) == "on"
}
// PublicKey implements HPKP to prevent MITM attacks with forged certificates. Default is "".
func GetSecurePublicKey() string {
return env.Get(ConsoleSecurePublicKey, "")
}
// ReferrerPolicy allows the Referrer-Policy header with the value to be set with a custom value. Default is "".
func GetSecureReferrerPolicy() string {
return env.Get(ConsoleSecureReferrerPolicy, "")
@@ -228,10 +251,6 @@ func GetSecureFeaturePolicy() string {
return env.Get(ConsoleSecureFeaturePolicy, "")
}
func GetSecureExpectCTHeader() string {
return env.Get(ConsoleSecureExpectCTHeader, "")
}
func getLogSearchAPIToken() string {
if v := env.Get(ConsoleLogQueryAuthToken, ""); v != "" {
return v
@@ -284,3 +303,7 @@ func getConsoleDevMode() bool {
func getConsoleAnimatedLogin() bool {
return strings.ToLower(env.Get(ConsoleAnimatedLogin, "on")) == "on"
}
func getConsoleBrowserRedirectURL() string {
return env.Get(ConsoleBrowserRedirectURL, "")
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"os"
@@ -54,7 +54,7 @@ func TestGetPort(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsolePort, tt.args.env)
assert.Equalf(t, tt.want, GetPort(), "GetPort()")
os.Unsetenv(ConsolePort)
@@ -87,7 +87,7 @@ func TestGetTLSPort(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleTLSPort, tt.args.env)
assert.Equalf(t, tt.want, GetTLSPort(), "GetTLSPort()")
os.Unsetenv(ConsoleTLSPort)
@@ -120,7 +120,7 @@ func TestGetSecureAllowedHosts(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleSecureAllowedHosts, tt.args.env)
assert.Equalf(t, tt.want, GetSecureAllowedHosts(), "GetSecureAllowedHosts()")
os.Unsetenv(ConsoleSecureAllowedHosts)
@@ -153,7 +153,7 @@ func TestGetSecureHostsProxyHeaders(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleSecureHostsProxyHeaders, tt.args.env)
assert.Equalf(t, tt.want, GetSecureHostsProxyHeaders(), "GetSecureHostsProxyHeaders()")
os.Unsetenv(ConsoleSecureHostsProxyHeaders)
@@ -186,7 +186,7 @@ func TestGetSecureSTSSeconds(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleSecureSTSSeconds, tt.args.env)
assert.Equalf(t, tt.want, GetSecureSTSSeconds(), "GetSecureSTSSeconds()")
os.Unsetenv(ConsoleSecureSTSSeconds)
@@ -219,7 +219,7 @@ func Test_getLogSearchAPIToken(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleLogQueryAuthToken, tt.args.env)
assert.Equalf(t, tt.want, getLogSearchAPIToken(), "getLogSearchAPIToken()")
os.Setenv(ConsoleLogQueryAuthToken, tt.args.env)
@@ -252,7 +252,7 @@ func Test_getPrometheusURL(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(PrometheusURL, tt.args.env)
assert.Equalf(t, tt.want, getPrometheusURL(), "getPrometheusURL()")
os.Setenv(PrometheusURL, tt.args.env)
@@ -285,7 +285,7 @@ func Test_getPrometheusJobID(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(PrometheusJobID, tt.args.env)
assert.Equalf(t, tt.want, getPrometheusJobID(), "getPrometheusJobID()")
os.Setenv(PrometheusJobID, tt.args.env)
@@ -318,7 +318,7 @@ func Test_getMaxConcurrentUploadsLimit(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleMaxConcurrentUploads, tt.args.env)
assert.Equalf(t, tt.want, getMaxConcurrentUploadsLimit(), "getMaxConcurrentUploadsLimit()")
os.Unsetenv(ConsoleMaxConcurrentUploads)
@@ -351,7 +351,7 @@ func Test_getMaxConcurrentDownloadsLimit(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleMaxConcurrentDownloads, tt.args.env)
assert.Equalf(t, tt.want, getMaxConcurrentDownloadsLimit(), "getMaxConcurrentDownloadsLimit()")
os.Unsetenv(ConsoleMaxConcurrentDownloads)
@@ -384,7 +384,7 @@ func Test_getConsoleDevMode(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
os.Setenv(ConsoleDevMode, tt.args.env)
assert.Equalf(t, tt.want, getConsoleDevMode(), "getConsoleDevMode()")
os.Unsetenv(ConsoleDevMode)

View File

@@ -16,7 +16,7 @@
// This file is safe to edit. Once it exists it will not be overwritten
package restapi
package api
import (
"bytes"
@@ -35,22 +35,24 @@ import (
"sync"
"time"
"github.com/google/uuid"
"github.com/minio/console/pkg/logger"
"github.com/minio/console/pkg/utils"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/klauspost/compress/gzhttp"
portal_ui "github.com/minio/console/portal-ui"
"github.com/minio/pkg/v2/env"
"github.com/minio/pkg/v2/mimedb"
xnet "github.com/minio/pkg/v2/net"
portal_ui "github.com/minio/console/web-app"
"github.com/minio/pkg/v3/env"
"github.com/minio/pkg/v3/mimedb"
xnet "github.com/minio/pkg/v3/net"
"github.com/go-openapi/errors"
"github.com/go-openapi/swag"
"github.com/minio/console/api/operations"
"github.com/minio/console/models"
"github.com/minio/console/pkg/auth"
"github.com/minio/console/restapi/operations"
"github.com/unrolled/secure"
)
@@ -80,7 +82,7 @@ func configureFlags(api *operations.ConsoleAPI) {
func configureAPI(api *operations.ConsoleAPI) http.Handler {
// Applies when the "x-token" header is set
api.KeyAuth = func(token string, scopes []string) (*models.Principal, error) {
api.KeyAuth = func(token string, _ []string) (*models.Principal, error) {
// we are validating the session token by decrypting the claims inside, if the operation succeed that means the jwt
// was generated and signed by us in the first place
if token == "Anonymous" {
@@ -101,7 +103,7 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
CustomStyleOb: claims.CustomStyleOB,
}, nil
}
api.AnonymousAuth = func(s string) (*models.Principal, error) {
api.AnonymousAuth = func(_ string) (*models.Principal, error) {
return &models.Principal{}, nil
}
@@ -168,6 +170,8 @@ func configureAPI(api *operations.ConsoleAPI) http.Handler {
registerReleasesHandlers(api)
registerPublicObjectsHandlers(api)
api.PreServerShutdown = func() {}
api.ServerShutdown = func() {}
@@ -192,11 +196,7 @@ func setupMiddlewares(handler http.Handler) http.Handler {
func ContextMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestID, err := utils.NewUUID()
if err != nil && err != auth.ErrNoAuthToken {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
requestID := uuid.NewString()
ctx := context.WithValue(r.Context(), utils.ContextRequestID, requestID)
ctx = context.WithValue(ctx, utils.ContextRequestUserAgent, r.UserAgent())
ctx = context.WithValue(ctx, utils.ContextRequestHost, r.Host)
@@ -256,10 +256,8 @@ func setupGlobalMiddleware(handler http.Handler) http.Handler {
BrowserXssFilter: GetSecureBrowserXSSFilter(),
ContentSecurityPolicy: GetSecureContentSecurityPolicy(),
ContentSecurityPolicyReportOnly: GetSecureContentSecurityPolicyReportOnly(),
PublicKey: GetSecurePublicKey(),
ReferrerPolicy: GetSecureReferrerPolicy(),
FeaturePolicy: GetSecureFeaturePolicy(),
ExpectCTHeader: GetSecureExpectCTHeader(),
IsDevelopment: false,
}
secureMiddleware := secure.New(secureOptions)
@@ -510,7 +508,7 @@ func replaceBaseInIndex(indexPageBytes []byte, basePath string) []byte {
func replaceLicense(indexPageBytes []byte) []byte {
indexPageStr := string(indexPageBytes)
newPlan := fmt.Sprintf("<meta name=\"minio-license\" content=\"%s\" />", InstanceLicensePlan.String())
indexPageStr = strings.Replace(indexPageStr, "<meta name=\"minio-license\" content=\"apgl\"/>", newPlan, 1)
indexPageStr = strings.Replace(indexPageStr, "<meta name=\"minio-license\" content=\"agpl\"/>", newPlan, 1)
indexPageBytes = []byte(indexPageStr)
return indexPageBytes
}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"os"
@@ -70,7 +70,7 @@ func Test_parseSubPath(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
assert.Equalf(t, tt.want, parseSubPath(tt.args.v), "parseSubPath(%v)", tt.args.v)
})
}
@@ -115,7 +115,7 @@ func Test_getSubPath(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
t.Setenv(SubPath, tt.args.envValue)
defer os.Unsetenv(SubPath)
subPathOnce = sync.Once{}

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
// list of all console environment constants
const (
@@ -56,6 +56,7 @@ const (
ConsoleMaxConcurrentDownloads = "CONSOLE_MAX_CONCURRENT_DOWNLOADS"
ConsoleDevMode = "CONSOLE_DEV_MODE"
ConsoleAnimatedLogin = "CONSOLE_ANIMATED_LOGIN"
ConsoleBrowserRedirectURL = "CONSOLE_BROWSER_REDIRECT_URL"
LogSearchQueryAuthToken = "LOGSEARCH_QUERY_AUTH_TOKEN"
SlashSeparator = "/"
LocalAddress = "127.0.0.1"

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
import (
"context"
@@ -39,7 +39,7 @@ import (
flags "github.com/jessevdk/go-flags"
"golang.org/x/net/netutil"
"github.com/minio/console/restapi/operations"
"github.com/minio/console/api/operations"
)
const (

View File

@@ -16,7 +16,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Package restapi MinIO Console Server
// Package api MinIO Console Server
//
// Schemes:
// http
@@ -35,4 +35,4 @@
// - application/json
//
// swagger:meta
package restapi
package api

View File

@@ -17,7 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
@@ -1762,6 +1762,11 @@ func init() {
"name": "prefix",
"in": "query",
"required": true
},
{
"type": "string",
"name": "versionID",
"in": "query"
}
],
"responses": {
@@ -2743,6 +2748,41 @@ func init() {
}
}
},
"/download-shared-object/{url}": {
"get": {
"security": [],
"produces": [
"application/octet-stream"
],
"tags": [
"Public"
],
"summary": "Downloads an object from a presigned url",
"operationId": "DownloadSharedObject",
"parameters": [
{
"type": "string",
"name": "url",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"type": "file"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/ApiError"
}
}
}
}
},
"/group/{name}": {
"get": {
"tags": [
@@ -2928,6 +2968,9 @@ func init() {
}
},
"post": {
"consumes": [
"application/json"
],
"tags": [
"idp"
],
@@ -3005,6 +3048,9 @@ func init() {
}
},
"put": {
"consumes": [
"application/json"
],
"tags": [
"idp"
],
@@ -4431,10 +4477,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/definitions/selectedSAs"
}
}
],
@@ -5268,10 +5311,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/definitions/selectedUsers"
}
}
],
@@ -5373,6 +5413,10 @@ func init() {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
@@ -5475,6 +5519,10 @@ func init() {
"type": "string"
}
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
@@ -6180,6 +6228,9 @@ func init() {
"type": "integer",
"format": "int64"
},
"delete_all": {
"type": "boolean"
},
"delete_marker": {
"type": "boolean"
},
@@ -7179,6 +7230,9 @@ func init() {
"replicateDeletes": {
"type": "boolean"
},
"replicateExistingObjects": {
"type": "boolean"
},
"replicateMetadata": {
"type": "boolean"
},
@@ -7988,6 +8042,18 @@ func init() {
}
}
},
"selectedSAs": {
"type": "array",
"items": {
"type": "string"
}
},
"selectedUsers": {
"type": "array",
"items": {
"type": "string"
}
},
"serverDrives": {
"type": "object",
"properties": {
@@ -8826,6 +8892,10 @@ func init() {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
@@ -10912,6 +10982,11 @@ func init() {
"name": "prefix",
"in": "query",
"required": true
},
{
"type": "string",
"name": "versionID",
"in": "query"
}
],
"responses": {
@@ -11901,6 +11976,41 @@ func init() {
}
}
},
"/download-shared-object/{url}": {
"get": {
"security": [],
"produces": [
"application/octet-stream"
],
"tags": [
"Public"
],
"summary": "Downloads an object from a presigned url",
"operationId": "DownloadSharedObject",
"parameters": [
{
"type": "string",
"name": "url",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"type": "file"
}
},
"default": {
"description": "Generic error response.",
"schema": {
"$ref": "#/definitions/ApiError"
}
}
}
}
},
"/group/{name}": {
"get": {
"tags": [
@@ -12094,6 +12204,9 @@ func init() {
}
},
"post": {
"consumes": [
"application/json"
],
"tags": [
"idp"
],
@@ -12171,6 +12284,9 @@ func init() {
}
},
"put": {
"consumes": [
"application/json"
],
"tags": [
"idp"
],
@@ -13613,10 +13729,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/definitions/selectedSAs"
}
}
],
@@ -14458,10 +14571,7 @@ func init() {
"in": "body",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/definitions/selectedUsers"
}
}
],
@@ -14717,6 +14827,10 @@ func init() {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
@@ -14819,6 +14933,10 @@ func init() {
"type": "string"
}
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
@@ -15519,6 +15637,9 @@ func init() {
"type": "integer",
"format": "int64"
},
"delete_all": {
"type": "boolean"
},
"delete_marker": {
"type": "boolean"
},
@@ -16518,6 +16639,9 @@ func init() {
"replicateDeletes": {
"type": "boolean"
},
"replicateExistingObjects": {
"type": "boolean"
},
"replicateMetadata": {
"type": "boolean"
},
@@ -17327,6 +17451,18 @@ func init() {
}
}
},
"selectedSAs": {
"type": "array",
"items": {
"type": "string"
}
},
"selectedUsers": {
"type": "array",
"items": {
"type": "string"
}
},
"serverDrives": {
"type": "object",
"properties": {
@@ -18148,6 +18284,10 @@ func init() {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_all": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"
},
"expired_object_delete_marker": {
"description": "Non required, toggle to disable or enable rule",
"type": "boolean"

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -53,6 +53,7 @@ var (
ErrAvoidSelfAccountDelete = errors.New("logged in user cannot be deleted by itself")
ErrAccessDenied = errors.New("access denied")
ErrOauth2Provider = errors.New("unable to contact configured identity provider")
ErrOauth2Login = errors.New("unable to login using configured identity provider")
ErrNonUniqueAccessKey = errors.New("access key already in use")
ErrRemoteTierExists = errors.New("specified remote tier already exists")
ErrRemoteTierNotFound = errors.New("specified remote tier was not found")
@@ -71,7 +72,6 @@ var (
ErrEncryptionConfigNotFound = errors.New("encryption configuration not found")
ErrPolicyNotFound = errors.New("policy does not exist")
ErrLoginNotAllowed = errors.New("login not allowed")
ErrSubnetUploadFail = errors.New("SUBNET upload failed")
ErrHealthReportFail = errors.New("failure to generate Health report")
)
@@ -84,10 +84,12 @@ type CodedAPIError struct {
func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
errorCode := 500
errorMessage := ErrDefault.Error()
var detailedMessage string
var err1 error
var exists bool
if len(err) > 0 {
if err1, exists = err[0].(error); exists {
detailedMessage = err1.Error()
var lastError error
if len(err) > 1 {
if err2, lastExists := err[1].(error); lastExists {
@@ -105,6 +107,7 @@ func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
errorMessage = ErrNotFound.Error()
}
if errors.Is(err1, ErrInvalidLogin) {
detailedMessage = ""
errorCode = 401
errorMessage = ErrInvalidLogin.Error()
}
@@ -114,10 +117,12 @@ func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
}
// If the last error is ErrInvalidLogin, this is a login failure
if errors.Is(lastError, ErrInvalidLogin) {
detailedMessage = ""
errorCode = 401
errorMessage = err1.Error()
}
if strings.Contains(err1.Error(), ErrLoginNotAllowed.Error()) {
detailedMessage = ""
errorCode = 400
errorMessage = ErrLoginNotAllowed.Error()
}
@@ -211,6 +216,7 @@ func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
errorMessage = ErrAccessDenied.Error()
}
if madmin.ToErrorResponse(err1).Code == "InvalidAccessKeyId" {
errorCode = 401
errorMessage = ErrInvalidSession.Error()
}
@@ -261,7 +267,7 @@ func ErrorWithContext(ctx context.Context, err ...interface{}) *CodedAPIError {
}
}
}
return &CodedAPIError{Code: errorCode, APIError: &models.APIError{Message: errorMessage, DetailedMessage: err1.Error()}}
return &CodedAPIError{Code: errorCode, APIError: &models.APIError{Message: errorMessage, DetailedMessage: detailedMessage}}
}
// Error receives an errors object and parse it against k8sErrors, returns the right errors code paired with a generic errors message

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"context"
@@ -44,37 +44,38 @@ func TestError(t *testing.T) {
}
appErrors := map[string]expectedError{
"ErrDefault": {code: 500, err: ErrDefault},
"ErrInvalidLogin": {code: 401, err: ErrInvalidLogin},
"ErrForbidden": {code: 403, err: ErrForbidden},
"ErrFileTooLarge": {code: 413, err: ErrFileTooLarge},
"ErrInvalidSession": {code: 401, err: ErrInvalidSession},
"ErrNotFound": {code: 404, err: ErrNotFound},
"ErrGroupAlreadyExists": {code: 400, err: ErrGroupAlreadyExists},
"ErrInvalidErasureCodingValue": {code: 400, err: ErrInvalidErasureCodingValue},
"ErrBucketBodyNotInRequest": {code: 400, err: ErrBucketBodyNotInRequest},
"ErrBucketNameNotInRequest": {code: 400, err: ErrBucketNameNotInRequest},
"ErrGroupBodyNotInRequest": {code: 400, err: ErrGroupBodyNotInRequest},
"ErrGroupNameNotInRequest": {code: 400, err: ErrGroupNameNotInRequest},
"ErrPolicyNameNotInRequest": {code: 400, err: ErrPolicyNameNotInRequest},
"ErrPolicyBodyNotInRequest": {code: 400, err: ErrPolicyBodyNotInRequest},
"ErrInvalidEncryptionAlgorithm": {code: 500, err: ErrInvalidEncryptionAlgorithm},
"ErrSSENotConfigured": {code: 404, err: ErrSSENotConfigured},
"ErrBucketLifeCycleNotConfigured": {code: 404, err: ErrBucketLifeCycleNotConfigured},
"ErrChangePassword": {code: 403, err: ErrChangePassword},
"ErrInvalidLicense": {code: 404, err: ErrInvalidLicense},
"ErrLicenseNotFound": {code: 404, err: ErrLicenseNotFound},
"ErrAvoidSelfAccountDelete": {code: 403, err: ErrAvoidSelfAccountDelete},
"ErrAccessDenied": {code: 403, err: ErrAccessDenied},
"ErrDefault": {code: 500, err: ErrDefault},
"ErrForbidden": {code: 403, err: ErrForbidden},
"ErrFileTooLarge": {code: 413, err: ErrFileTooLarge},
"ErrInvalidSession": {code: 401, err: ErrInvalidSession},
"ErrNotFound": {code: 404, err: ErrNotFound},
"ErrGroupAlreadyExists": {code: 400, err: ErrGroupAlreadyExists},
"ErrInvalidErasureCodingValue": {code: 400, err: ErrInvalidErasureCodingValue},
"ErrBucketBodyNotInRequest": {code: 400, err: ErrBucketBodyNotInRequest},
"ErrBucketNameNotInRequest": {code: 400, err: ErrBucketNameNotInRequest},
"ErrGroupBodyNotInRequest": {code: 400, err: ErrGroupBodyNotInRequest},
"ErrGroupNameNotInRequest": {code: 400, err: ErrGroupNameNotInRequest},
"ErrPolicyNameNotInRequest": {code: 400, err: ErrPolicyNameNotInRequest},
"ErrPolicyBodyNotInRequest": {code: 400, err: ErrPolicyBodyNotInRequest},
"ErrInvalidEncryptionAlgorithm": {code: 500, err: ErrInvalidEncryptionAlgorithm},
"ErrSSENotConfigured": {code: 404, err: ErrSSENotConfigured},
"ErrBucketLifeCycleNotConfigured": {code: 404, err: ErrBucketLifeCycleNotConfigured},
"ErrChangePassword": {code: 403, err: ErrChangePassword},
"ErrInvalidLicense": {code: 404, err: ErrInvalidLicense},
"ErrLicenseNotFound": {code: 404, err: ErrLicenseNotFound},
"ErrAvoidSelfAccountDelete": {code: 403, err: ErrAvoidSelfAccountDelete},
"ErrNonUniqueAccessKey": {code: 500, err: ErrNonUniqueAccessKey},
"ErrRemoteTierExists": {code: 400, err: ErrRemoteTierExists},
"ErrRemoteTierNotFound": {code: 400, err: ErrRemoteTierNotFound},
"ErrRemoteTierUppercase": {code: 400, err: ErrRemoteTierUppercase},
"ErrRemoteTierBucketNotFound": {code: 400, err: ErrRemoteTierBucketNotFound},
"ErrRemoteInvalidCredentials": {code: 403, err: ErrRemoteInvalidCredentials},
"ErrTooFewNodes": {code: 500, err: ErrTooFewNodes},
"ErrUnableToGetTenantUsage": {code: 500, err: ErrUnableToGetTenantUsage},
"ErrTooManyNodes": {code: 500, err: ErrTooManyNodes},
"ErrTooFewNodes": {code: 500, err: ErrTooFewNodes},
"ErrAccessDenied": {code: 403, err: ErrAccessDenied},
"ErrTooFewAvailableNodes": {code: 500, err: ErrTooFewAvailableNodes},
"ErrFewerThanFourNodes": {code: 500, err: ErrFewerThanFourNodes},
"ErrUnableToGetTenantLogs": {code: 500, err: ErrUnableToGetTenantLogs},
@@ -96,6 +97,7 @@ func TestError(t *testing.T) {
},
})
}
tests = append(tests,
testError{
name: "passing multiple errors but ErrInvalidLogin is last",
@@ -104,11 +106,23 @@ func TestError(t *testing.T) {
},
want: &CodedAPIError{
Code: int(401),
APIError: &models.APIError{Message: ErrDefault.Error(), DetailedMessage: ErrDefault.Error()},
APIError: &models.APIError{Message: ErrDefault.Error(), DetailedMessage: ""},
},
})
tests = append(tests,
testError{
name: "login error omits detailedMessage",
args: args{
err: []interface{}{ErrInvalidLogin},
},
want: &CodedAPIError{
Code: int(401),
APIError: &models.APIError{Message: ErrInvalidLogin.Error(), DetailedMessage: ""},
},
})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
got := Error(tt.args.err...)
assert.Equalf(t, tt.want.Code, got.Code, "Error(%v) Got (%v)", tt.want.Code, got.Code)
assert.Equalf(t, tt.want.APIError.DetailedMessage, got.APIError.DetailedMessage, "Error(%s) Got (%s)", tt.want.APIError.DetailedMessage, got.APIError.DetailedMessage)
@@ -138,7 +152,7 @@ func TestErrorWithContext(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
assert.Equalf(t, tt.want, ErrorWithContext(tt.args.ctx, tt.args.err...), "ErrorWithContext(%v, %v)", tt.args.ctx, tt.args.err)
})
}

View File

@@ -14,12 +14,14 @@
// 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 restapi
package api
import (
"net/http"
"os"
"github.com/minio/console/pkg/subnet"
"github.com/minio/pkg/v3/licverifier"
"github.com/minio/pkg/v3/subnet"
)
type SubnetPlan int
@@ -43,8 +45,18 @@ func (sp SubnetPlan) String() string {
var InstanceLicensePlan = PlanAGPL
func getLicenseInfo(client http.Client, license string) (*licverifier.LicenseInfo, error) {
lv := subnet.LicenseValidator{
Client: client,
ExpiryGracePeriod: 0,
}
lv.Init(getConsoleDevMode())
return lv.ParseLicense(license)
}
func fetchLicensePlan() {
licenseInfo, err := subnet.ParseLicense(GetConsoleHTTPClient("", "127.0.0.1"), os.Getenv(EnvSubnetLicense))
client := GetConsoleHTTPClient("127.0.0.1")
licenseInfo, err := getLicenseInfo(*client, os.Getenv(EnvSubnetLicense))
if err != nil {
return
}

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
package restapi
package api
import (
"context"
@@ -58,7 +58,7 @@ type Context struct {
TLSCertificate, TLSKey, TLSca string
}
// Load loads restapi Context from command line context.
// Load loads api Context from command line context.
func (c *Context) Load(ctx *cli.Context) error {
*c = Context{
Host: ctx.String("host"),

View File

@@ -14,7 +14,7 @@
// 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 restapi
package api
import (
"flag"
@@ -85,7 +85,7 @@ func TestContext_Load(t *testing.T) {
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Run(tt.name, func(_ *testing.T) {
c := &Context{}
fs := flag.NewFlagSet("flags", flag.ContinueOnError)

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