From cf437a4948d208af64b5cff6ddf543af92847268 Mon Sep 17 00:00:00 2001 From: Mitchell Shiell <59712867+MitchellShiell@users.noreply.github.com> Date: Wed, 11 Jan 2023 10:18:04 -0500 Subject: [PATCH 01/18] Readme updated --- README.md | 139 +++++++++++++++++---------------------------- code_of_conduct.md | 133 +++++++++++++++++++++++++++++++++++++++++++ icon-score.png | Bin 0 -> 21694 bytes ov-logo.png | Bin 0 -> 35498 bytes 4 files changed, 186 insertions(+), 86 deletions(-) create mode 100755 code_of_conduct.md create mode 100755 icon-score.png create mode 100755 ov-logo.png diff --git a/README.md b/README.md index e6ac3456..7f60dce2 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,73 @@ -

SCORe

+# Score - Genomic File Transfer & Object Storage -

Secure Cloud Object Repository

+[](http://slack.overture.bio) +[](https://github.com/overture-stack/score/blob/develop/LICENSE) +[](code_of_conduct.md) -

Formerly known as ICGC Storage and currently used as the storage and transfer system for ICGC cloud based projects against S3 and Azure backends.

+
+score-logo +
-

General Availability

+Genomics data volume and velocity have increased dramatically, rendering on-premise storage insufficient and demanding specialized software tools to manage these large and complex data sets in the cloud. [Score](https://www.overture.bio/documentation/score/) addresses this by facilitating the transfer and storage of genomics data to and from a distributed cloud network. -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/201ae314ab3842baad25bc820069e90a)](https://www.codacy.com/app/overture-stack/score?utm_source=github.com&utm_medium=referral&utm_content=overture-stack/score&utm_campaign=Badge_Grade) -[![Documentation Status](https://readthedocs.org/projects/score-docs/badge/?version=latest)](https://score-docs.readthedocs.io/en/latest/?badge=latest) -[![Slack](http://slack.overture.bio/badge.svg)](http://slack.overture.bio) + -## Documentation - -Explore documentation with the Score [Read the Docs](https://score-docs.readthedocs.io/en/develop/introduction.html). - -## Build - -To compile, test and package the system, execute the following from the root of the repository: - -```shell -mvn -``` - -## Run - -See module-specific documentation below. +
-## Modules -Top level system modules: +> +>
+> +>
e +> +> *Score is a vital service within the [Overture](https://www.overture.bio/) research software ecosystem. With our genomics data management solutions, scientists can significantly improve the lifecycle of their data and the quality of their research. See our [related products](#related-products) for more information on what Overture can offer.* +> +> + -- [Core](score-core/README.md) -- [Client](score-client/README.md) -- [File System](score-fs/README.md) -- [Server](score-server/README.md) -- [Test](score-test/README.md) +## Technical Specifications -## Development -Several `make` targets are provided for locally deploying dependent services using docker. -By using this, the developer will be able to replicate a live environment for score-server and score-client. -It allows the user to develop locally, and test uploads/downloads in an isolated environment. +- Written in JAVA +- Supports AWS S3, Azure, Google Cloud, Openstack with Ceph, Minio and all other S3-compliant cloud storage solutions +- Built-in [Samtools](http://www.htslib.org/) functionality including BAM and CRAM file slicing by genomic region +- ACL security using [OAuth 2.0](https://oauth.net/2/) and scopes based on study codes +- Multipart Uploads and Downloads +- REST API with [Swagger UI](https://swagger.io/tools/swagger-ui/) +- [MD5sum](https://www.intel.com/content/www/us/en/support/programmable/articles/000078103.html) validation -There are 2 modes: - -### 1. Development Mode -The purpose of this mode is to decrease the wait time between building and testing against dependent services. -This mode will run a `mvn package` if the `*-dist.tar.gz` files are missing, and copy them into a container for them to be run. -This method allows for fast developement, since the `mvn package` step is handled on the **Docker host**. -In addition, the debug ports `5005` and `5006` are exposed for both `score-client` and `score-server`, respectively, allowing developers to debug the docker containers. -This mode can be enabled using the `DEMO_MODE=0` override. This is the default behaviour if the variable `DEMO_MODE` is not defined. - -#### Debugging the score-client with IntelliJ -Since the JVM debug port is exposed by the `score-client` docker container, IntelliJ can **remotely debug** a running docker container. -To do this, a **docker image run profile** must be created with the configuration outputted by the `make intellij-score-client-config` command, which will output a basic upload command, however it can be modified to be any score-client command. -Then, a **remote debug profile** must be created, with the following config: - -``` -Host: localhost -Port: 5005 -Use module classpath: score-client -``` -and in the `Before launch: Activate tool window` section, click the `+` sign, and select `Launch docker before debug`. -Then ensure the `Docker configuration` field is set to the name of the previously created **docker image run profile** and that `Custom Options` is set to `-p 5005:5005`. In order for the debugger to bind to the debug port in time, -a delay needs to be introduced after starting the container. To do this, click the `+` sign again, and select `Launch docker before debug`, and select `Run External Tool` and a window will pop-up. Input the following: - -``` -Name: Sleep for 5 seconds -Program: /usr/bin/sleep -Arguments: 5 -``` -and click `OK`. - -Finally, start debugging by simply running the **remote debug profile** and it will call the **docker image run profile** before launch. +## Documentation -#### Debugging the score-server with IntelliJ -Since the `score-server` is a server and exposes the 5006 debug port, configuration is much easier. First, start the server with `make clean start-score-server`. Then, create a **remote debug profile** in Intellij with the following configuration: -``` -Host: localhost -Port: 5006 -Use module classpath: score-server -``` -and then run it in debug mode. +- See our Developer [wiki](https://github.com/overture-stack/score/wiki) +- For our user installation guide see our website [here](https://www.overture.bio/documentation/score/installation/installation/) +- For user guidance see our website [here](https://www.overture.bio/documentation/score/user-guide/admin-ui/) +## Support & Contributions +- Filing an [issue](https://github.com/overture-stack/score/issues) +- Making a [contribution](CONTRIBUTING.md) +- Connect with us on [Slack](http://slack.overture.bio) +- Add or Upvote a [feature request](https://github.com/overture-stack/score/issues?q=is%3Aopen+is%3Aissue+label%3Anew-feature+sort%3Areactions-%2B1-desc) -### 2. Demo Mode -The purpose of this mode is to demo the current `score-server` and `score-client` code by building it in **inside the Docker image**, -as opposed to the **Docker host** as is done in Development mode and then running the containers. -This mode will not run `mvn package` on the Docker host, but instead inside the Docker container. -This method is very slow, since maven will download dependencies every time a build is triggered, however creates a completely isolated environment for testing. -This mode can be enabled using the `DEMO_MODE=1` make variable override. For example, to start the score-server, the following command would be run: +## Related Products -```bash -make start-score-server DEMO_MODE=1 -``` +
+ Overture overview +
-For more information on the different targets, run `make help` or read the comments above each target for a description +Overture is an ecosystem of research software tools, each with narrow responsibilities, designed to address the changing needs of genomics research. +Score commonly works in tandem with our metadata service, [Song](https://github.com/overture-stack/SONG). As Score facilitates object storage in the cloud, Song runs in parallel to validate and track files and associated metadata. -## Changes +These tools are part of the Overture **Data Management System** (DMS), a fully functional and customizable data portal built from a packaged collection of Overtures microservices. For more information on DMS, read our [DMS documentation](https://www.overture.bio/documentation/dms/). -Change log for the user-facing system modules may be found in [CHANGES.md](CHANGES.md). +See the links below for additional information on our other research software tools: -## License +
-Copyright and license information may be found in [LICENSE.md](LICENSE.md). +|Product|Description| +|---|---| +|[Ego](https://www.overture.bio/products/ego/)|An authorization and user management service| +|[Ego UI](https://www.overture.bio/products/ego-ui/)|A UI for managing EGO authentication and authorization services| +|[Score](https://www.overture.bio/products/score/)| Transfer data quickly and easily to and from any cloud-based storage system| +|[Song](https://www.overture.bio/products/song/)|Catalog and manage metadata of genomics data spread across cloud storage systems| +|[Maestro](https://www.overture.bio/products/maestro/)|Organizing your distributed data into a centralized Elasticsearch index| +|[Arranger](https://www.overture.bio/products/arranger/)|Organize an intuitive data search interface, complete with customizable components, tables, and search terms| \ No newline at end of file diff --git a/code_of_conduct.md b/code_of_conduct.md new file mode 100755 index 00000000..45d257b2 --- /dev/null +++ b/code_of_conduct.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/icon-score.png b/icon-score.png new file mode 100755 index 0000000000000000000000000000000000000000..0ba74bdb0e7646b47e465a2fe3d1039189643273 GIT binary patch literal 21694 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 literal 0 HcmV?d00001 diff --git a/ov-logo.png b/ov-logo.png new file mode 100755 index 0000000000000000000000000000000000000000..51fda130b2507903c47256af9754f7f20dedf516 GIT binary patch literal 35498 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%0A4wG@6=tNvfNwoRk;RpzVz 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

C~gHIi9ocObYjfv^NM4ltsJMXln%geIi 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≦S9g3Vaqg&~yEUzMa2%-)Oma z&`XIVCA4eT-FGF(GC0gqJ4qIr(fRIG%4z8@y5c)Z;%ljB;u4WgKi6tIvb#r0`o3NL zUf$EpRs-|($zWnCw9TTUobKngI;3gV%cI9vevhXdg*3^0puzHeE>%1X@KxYZMCiX| z>&DUhuP=GUf;A-Tse#f8A;i^I6wf!p^WCH5JF2hX>YS@2G3NAOqAsT}2Ey3dckCPT zAJ{$Mx1-d4<4|qsl~~WlN@5Rl;W2Jq-Y}`P#u23CDyQfOBFq3YoY4&EQpLlP&9nVF z@PgM{=-c@l_m&5?Z?T}#gm^s{QoRAh#zCCMtuQ^`J(Oe)({CyC0DG#0-5D;ir0J6e;xRYQ}EdI z^S5s8yJ2&$Lfe!m>0UQ8vQNPhRU1h#SC0WAV^0kpTE=$Ltk-o%nKy`1LOV)HQp5Xh zANF^T7B$xL;%v}*IZ?AI7)`gpYBh;di!X{^PYZ}43(;23ywB?uk0mn4=_{gD|DM15 z$k^C}Hx?4&)DU;SOJF&bDwwUu&6A5EWEHJvOKV~+u`w8H=titgqXgPfCbc_9iq6B= z_4_?}M?F5#YW~&X#zae;KoC^-YPBjX$I~NY4PwPpxMXgN8L}Rxr+6dVjVFOW2HK-< z+q-4!2ksau=K5_)V!Kx4DWpA9ja$d&BLGKUo6k{jwe;j&@f9#mn#sakj#!<-<@d9hFS-@>n2)NvfK`9i;k!*MO_%lIYmxe9>JOSeWQ-f1v2a7VE=7f z2Y3APy_<^zy$VIA!r|IxIdmN@wd2>H{|u^ zJz1=Ud~GtAe4%CLbFNalYjvy|!g32sY{3ydlGpiOUwLGf$1E!(9u460z)t{%?%XkQ z-QRp`UKd=OcIqy#ZL+b|Nj-?0#}}G5J-48GjuKZ3={25R-5IPzJxJ_e*;8-bJK){D zz1I&CW4?H(Hv8m!v>2cg-;r)qZurlIt9QZU@<*nWK58u6M z*RS4NHbh~1>h-RzYldW*8#ZdT;@W|kAPwWJ&+*yeT2D)V(N#sy(Z*PNtyI{aMyR%8 z(^GWiT{jQ=Z{IiM=RGaoJ6x}Q;y`_BKBk>_ly;P;ZZLaw5wcl71{lmc-i>{3?{H4L zWXWMif!9=duGAj#Dd67&3;s~4Z|6tv-@NtVJ9BMnVUoS(wRKJaS$ke9Nh63G;|mSW zVTKhvNBWAs%KKW3y?mY2uQbaVT5ZQBG1lI(y~la~ZNs^8PRohemif$)#`Mo>>6Gg^ zRtsG(>186xrs2`&iL+d*Ar^)75ubOzY$O`BFJuo%$z@Dx9{?2=L4~%VfV`(HY zfl*vrGnNG<79m<{#q*CJsfOpMu+95g^%h-~b5&+CUITWyblf{pVyU%b?%dw%e&o)v z{LZ1G4%!j_{gtJYUzv$cw6zY3j=0@MmzM_-NDVegttq)mZL7EiFLRb2AZtguYT^Nz zdGqgquZXJ{d&iAiZ~pr~zo|IduOpgqLTKfh5fF=@MZgBNT0H&zmzRR+rPqjur-gx% ztBamiNt!hWTF-{Za)Z$zOl>nt%&w85{@7g`^7rlT^ICCgK6hYg?o%g%Ba^Ar`+V(c zYuEF~v8J#f25Vi7jOJCo;)+K$xB6wWvXs|o_)3b$a^>wG0$=fmO75Qj>79FazweQL zzfzJm)oaRus!)JP7&gufOOh2bdu9cbt>e z*iQZk_;0`~Zr=57`~Uvpj$I$PzsF$0Ix~qz%Qck)Vy%r9TXE6~&Y7z2IZDdDlhv26 z^Xi~9#V!S@sT3Xgz#Sw0yKWlx%Xvqh8m~8h|C#v{FSqStZ_aTlp15&0W&g4vWGU$i z?53iVyKf{v*yAb4f+2^__qf$Mi$4eaABfE6H&h01`zIf|Ztq7Q=?`gy4HgoMK`nR2 zU8iL2|CNZ*5-qlp*`FO=3>TXLyxO;sbF~cj_^OoCf?(Hcx|je)-j#9;4GJU@1;XtgLGRu_%;iw2EvaKKbqE=I5U{T0i?< zc~3Fc>#N?PrvxjhG3#ohzg#cT3{$I=@bKON@1u8*<%de1T5Lr2&-d5Hzc3jck6kzF z^OUCqF=waZc3D-j{6tHir@U=Nr&Q3Q$)YST0OxI`xtjZjIWh<8e+Q~V_wL+y@4xts zJ=-6;yI1*|h(>43^Ljc}&PD;6geYBj{#dhqU^;+T4>>9LS~m6PbZ@~`B0{>(K9c46 zEn11(v$N0prF+H-H*7393#}yiZ_h4Fd~!TEwxHeShJur`#z z?DuurN4!kt^EfZ7?RY16&`>Nodpy7%@zgE1kEQdoWQuwWIbiA4}Raym+ac=~4t7H1wkxOn!x%6V6neMeFQacb5@ z#6=0T!W08?{l<#>TMun6-oCZRGl}6_N9zl}f24I_-l|r`RjwyErYjs*1Pd60DLCS6 zE;^NdPvs@+-SKVU#DyMvxxyX?$hI*5QM3dj5AGhh^`Cxl_s(}cIABQ9m>@Nnbvr=H z!Bq)?nS1GQWA?`fYiIx7b40cc6`a1Jt3(iEul{80T061ET6^dAUgtL-*i^W4TaT+O zeD-i-`ad3M9z4)8OP&_Vb+QM$%5i0|*%gj`y?*hAUayZV8SFW-68sBtDdQ$riWh-@ zLw20}(%3t07*<+AYWGk4@cCL2wvCX}St8kbJCsBeO0}n};leY=>rpL;y-M!X*Z@x} z_G~CRoBDFP+KNn+8a#a!Ce%sh-w0!4i#bQ`+TQDa^sWuLJ9qTDQDXSQk^0OZ9%vkS zVkw#Hb;a@JlyI!KFZ`;&T9%73?Oj8D-|d6`0NGCA+hhr17exQ_fBw%`b%AHGMAief z2iRNO(m&95!$zk)z7(}5mf|D|P1c8Ny>*%s1SKX-jZ)h7>=?-xHuo2ls}+D!i0deM zd7_ydpKYg!$?`w0^r~MkNt!iv&beCNe#4;m+YfFk?%Pyxt3i@{<7i{?_YX7aPr z8}IuMzj@=1kKQ-z_&$apU4O;t7MGkh#Ag2Zk;cidJ+~Ow+NUy3l?WSqb85KkDXm2k zW3H+VoRE3!>p^02j^@2L5BtCQ;HJX%;i6t>#p!4FSLgrl{f$=+G)=AKsIG9V5ju^I z<>3wazMU1fhb+MHGTAQS{IgO!T+VIFnVbOr9Z*-E^LL9|2KsOPXTPwcFjP_d|J!$_ z>(jH5!ch*s$_mV`ejfmU!cj>*GINg|t~QU)xALPs{+YiY>(A-IvZq?}X=*yo*0suV zi~ba7g{iH!W3zjts6Tf1SpJQR`t_EQqqk*s#`$dv=c%d-seLb>7uy+<}veL3(Vim52yRo!tRsZLqwd3Swg$ zVPaFP+`6^L{ndLn72bdANUpc&s-ufR_-FfTJ@qnz5?in%x8FkCKtvxr4_4@r~*EG|#HMJOq zaWfV~6k24t&CXSdLMwx@?RY74@%6w>+bV@keYxe|50-s3z8Iv>o~R{pVsW)vbG`RO zGIO^br8Y{e?Jc-+@2-CDZ#=NM@QxdYd{K&LXWI2YdTHszU!4fXClgv_S2>Dj#@ zpERPVer&oKg!NS6$kpyhl~Y|J4dF~P>fg7iIC$5NUOI^#0?gJT^W2GA(g+jlXpysr zMO|?$w4&6;iD6@ZUccv-VgG-4+t$MMViS6@?= zkZYfm%tv)gzgPa<8+x|)`P!GP9_^1fN3YWJu@=N*nS*3aM_duPuDG$UGI+<%UawG) z>dO<2R&z0m2#kZP9XxflI#mTF8b{T_sg_?TdINj6R&pbiQ@)Q@lyYJ*NT;fi$rRg}LxovBY`x_5zE_~$f4f+0pt6D)~KlRGe)W3edzW=FOy5MRhMMpX3 zn6%mD3Zj68AWb$GUH!pr#i9F0a~pNGJO01Owk?;;S`rU{DKY_>L}ZKCTiDQl^VWfZ zeOrqXifx^o59-lOkPsP{f^&6N=4N5rkY<`LBuUTMNMZ0TJ9?LYTh2RD4^sR1k!qA0 ziwL5xpn7N}#HnSmm6%qP+R+|g-gVP(?pN>KSa@(xpXX}Lk;O3hFE1?}`!5GuhhJ&g zTEP>?*P?Y-IMy6mkcqa59~{e9{_gdaZGE23kvU2KoGcQ0>Cd&s#A7*~{W-F2Oy0@6 zW0jpFgME89_vFfD9WMn@t6B}?w4E9ft8kRUxylYw!NJkZ#$2FWM>f3WhJLpv?}&)F zT8Xh%o;tP^x56xQUti|E%d(|mfqFYJ%`mm4oTF~v(&K#it_}H*-aVGTZbQjwB{u!e z@y5b`erf6GU!DlY$3xrf%PFrX>p~@0rD?cMS)T4OADDDFuhp;YDs6h(hWuu-`Ah#h z@O>_l*Ksy$O+1zff#*B7oM^SPFxFcfzH{e5-}bSBjYwP53sDjW#+odxJv+Ouw1I!= zIOKGjr8sW4lR}~28@OX@&vMe3vDk%XY>v;j(=aiYRXmnU=;PE9CdQ@)#`=8y_8SKM zU%GoN|H!@}znphCT#ed)abW4>@4r$%^tH)gI#DVaD?0g-#*NK7iLI|AL?8t_)lQ;c z+EE_()t#lCy}lCQ8^C`8s;~Ds*Q$6dGY$NhY;Hu4$~hZ)_Kx+BJ#fQdu29kGToBb3 zX4_%fOf{~)%C<39;i#n6PNHfv9((wPzT9w+4@lnCD(`6d>5>0`duJXb*L9uu@7(*g zUZ;EZ4ZsXAg8_yhNCK2WiYB!skwi+SELyghL`iJ9WXDomvP*U)aVn{DC2_fI|6`|; zI8G(8V^(A;s&W#Wwq=SUMTwF~EhNQ75C8%*zzk;To|*2Re*Lz4PyV>w#F*xWZO{X} zU!iL-gQ?dK-S2&U?z!iDXFaa@CULr5o3=#8D$oxVgTZ%Bmz|H_IhOgcBg5Xlp`0a% z@YI68@tzc*meS1k=Cr zuK@fIZ*zNgE8Q+0fSFiz8m6qh4q&&HbNfpN$IAV;O%@76{cgPC$F=H`AHi1wwvc9L z=Gvb1Tf(qliwLd6kLqzx@332%87){j#}a~&aiw^6z7bV6L)Mxh#MS#B2?9tE{7CWQ zdZ1&)IJB#1KXCg<=HqvaW{&MGJ6T82+(zhs;g!vW|9-qa_q9s28ZcDZ7LF~_=?LA7 zBSGttPBucV|H*W||GwS1$)Y110AGellm>5ch}UH&hzDSnF^e!2aA%1~SUIPVpBNbI zJ+ynUG&P?0yn^IV>1Mqe1iGF8APKt*_A1^O(Jr@AQNsRwwKZ^Ts#KU9$N@mRwS`VD zHG(xq4e*oc@z#p+1E>wNZ5d3vVD?gj7+j8(?VmwN1- zA|4$!0Xz>Ag;YUst-RY;x@okx|MtE8`H_K)giS(As5sGa=qDPgJ%Fj(%B_s`n}j0; z3#?bqHEla9dk^d?xP5s?5YbrKlgAgE@#z&`S@O!1n|2P7D2>f9(NV%Ec#@`va`MjU zUgu*!GMc^r=x}CgC?|YIbh;L`K7X>l@IQXonEPfWUaQ6kJxj= zCqhEF+)UUaAnr_5Vwk#v?$MD8JtB&l$E&UEP}v#0Yr0GXax6iOAm+1czOHUY+P=(A zTLwdE^HK;w5JWUobj7=8``v$h*RJdb4-b0#NAl8^f=|_B|KSt$#XmUSIQ25i;aI+$WA9Y)0L-@1DvZPP zHvp`HFl6W5{^Hb7&(J+H{eyQ+_jo;d8Jyb)n)S6nAwhdvcgu%(HwX!l4M#TPwa{`L zQJxvkW=G2z0O-lubhaAkXXolk&bzcN>5eUEq8Waqm;s&`$jJxZG2;D$caCM>bFkl; z9L!j*Eor5hgnx3XaqjnCsGWLzDXh%-%7-B29br4&S1q6NW-xf6rJ`d4Ug487#k~hg z_5hjX|L*~K^l}e>t-5Nj6dGoW>1mi9nXiKAm~gBIvZLi&y}rUg>A+b3?t5?Bz4qe# z+R_t0SUvyP%hg7GH2|});7T*ujXHfZbit)yyFXV2EO>J1@#E_!|M;o%rCWCQNL$L` z9#7 zFj4x$Fdw#;&GqJ1O#sROZU=A=fMWoT0w}3gL>n(HMl0VuS*gFWr_rW{It(+@Y z>XCl<>BZI`K6%!6EkPN_1OVE!RU1br&8%Uf3}!~68IC0|T5{#oP~I9Zd)Dk|ULG1R zSp7v;06-;B!SPz$c(xMOo~;D6?{CDlMPG%A!LB4}2_mbValWpulIs`&Al5)rX$2tu z)J&o8XJ(3r#&cF4W_RUR@g}oaE{5w(JhtKjxCy|$0B!?t5Wp?~d7UWKURY=@KKf#1 zgfry@)ugAar$f?a&R(+*4!?6W%TQ~sI=p+T9H)o6fyemr?iw260I53*Gk4*H~ zW95vnBq7qAEVh(CUys9YF16O4SPE8OswWLUVRi)xTYzi;slj8WpNMci+cHMyAVz~6ii6k=_; zj@bKCcMaYAs~_51zG826VkP|jublDcD=k&nwTR zs?NmZClqTi69^2=8i_U|IRzd4m7m&s%jZ74*BQ)v=hg!CUmu@qJ^90GC|_T68>Nuo#;FT--oHvkobRYm(0HZL`$0&d!FnN+$ z07IL%j#W*n|H!`5meiPkoQ=EAyPJF(Pgyt3Q~s`V&r`if(%IcDZKQT*zx zM23a}L%rb(+?i)9VYL&rnn?%+GWX=a>WX{m+vma+uV zXvvj*IZNa+4ul}qfUd=yEHvWQ_t&G1XDZRgiH*3`j8(E0>2M>`v1W!VNk}5Pibbm_ z+eGILR18}3RWgu~$)^q!20uMpJeaXWfy^@H-@`bfU)krr0mb9BNEi{>4`2eo7=YaX zrrKWz0TjTnR2U;%Yod8>Eom*T`_Wn}id(HjM@q%DPzBX`k~D(^L=-opC|qr{lDe;6 zFZf{1%nWvVGIn;Pl#^MWr}5QBG275Z0 z`_xSFz#_i zC4l(-;~DR>hk9;0SaL>S%(Z?U#v$x)4H~;5&!39N+rohnki9U%vI|C3iZIF749qN= z!S?T}_V@X>acl*k(SFzfd>AV@A3z<9x{i}Y*19GfdyoV@2w?EJwW$7E&#%Am@QKX@ zA;})dN-rx(UQ6Skl>a>HIx7bU_>PY^M>`qL@PF4KV;o7)04VcV$(td>P zV^;wD+`*DP{__WmQ_YBzM;C+jM#M=^R!HC?9bHm(ByAI8+Kf3o(r>$;o-Ixt?sN9E z>j(c7z<-8S(WCNzDspts$)SZKF|7T{4 z2{Yq~^TAp@)=AD1Qc_yrb-mFMj#z_z#mP-&+xq1G;`onG?pSMZfYh13CR=kgp(x$)xwg7=JNhJW!;&-CH4n@|LXoVFrnT(~bGBErr#Mh?9a%GOZ@vc}Oy&J*$C+((J!$B;)+_ zOkwwXM>126BnQAZ0sJOR5!kkqipTZAGXQ=YfU*VM_jkuLL&G`g_InNIFVD7C8?jav z5iF4k$WDO(1d0(U)&)!GV?&<(vopo1dxqU9m>QrbVT9wauh}`KTeV%zmaSUpIdApb z(*QmT;Nt*#&oq+e|2)|^{ik!y9l=3(o5jl(y8AF6{D4~*5LTIKF4}+ zUt##(UAf6VPxQ3CNB>*6Nhk5P*aMKhd0MP6jeky>rmZ{KRB#{GCJIWY!WA#y0Q|0ek_M z>3Du6NyVevxpeUW%(Zz3fL{jiZUFtK>xuu+$<5PGF1IQt>v1d6%$_7^8GnydK(?7! zGY1+>V4f;i;sfKk%unvik51&R37A%eF9Y~5?XR2H@?2j_Djwa=<%tJi1Y{JzF9P^S z0EPp_$yXLz3lE)YEPQ=AsQC#vCrNsi8Lg0B5mz5mX3l6PoOn{`qy3Ke5BKGVKQfWq z4WIzybp8;4-vMwOUHG=7;?eC~zIb#fz<9WRnt`K1qA}l08ecr^&wb&Q&4szmBmf|L zT;b#`5&-y(J*i4w#LahWioGLoFZ+EtM-|pAj z&wK;ZnKB$HrfR4eKscP0>efCd`}g(kAzW#^&~$pKTomojW@;%$ zD`q7Ki3V__&&3CJWlQfEaP}PObH{8!3{xrmMF9U7zz?v^rRJAHDjwa=)e(;l#{m2s zfDgksq*+g|hRa_(-8}oX|=_nb^lr3~naO3A5gnwbk9j zZvKJEeE%JT?wBp83{$)DB>=wK|axY92@}mH})j$Q`UJaKX zTlCL=X(3oYRZp}hVfA}L$o4R(l-H*-UocX@g0B#39n6-T}`GS(EG+R6T=x< zV$;m{986y0f5W)R?WlZpDjwa=)fW$f@mk#r;6ng@9KbDsVrw-}!B@`*%TF!^3*TA| z)_+io6*FYNCuGSHQUIhltuZ42(hMpUl|ajtK*hF1^QMxkZ|!x8?;p?h-#z3Fc@_;9 zY(au>3TBD&2ux>m6+6&9G8K<*=jw|`2LjLwGsEUy0Ph2E&`-3r)KblFtb|K{btt}$i=LyS^#->QO&-X@vV4{q6PJ`A$g-F3KIU<}WSoUn$>A812mpR<$ z>>bI-fviO_fKvdT2k`%38rr(1;OkOI#iQHVKJnN}8K$W0g8+U6z)YyvJJ(G7xy@wt z&*%Nh*H?mCHBg~qP^1}>K#mZ?7CS8VzDPPbjhLAt#jF|1A}C7;nXyRUHRL5fwmaK< zuxuY3%UOLEQ47X8@Gj92O{FiV+_YVa;*&|1jJ$$GT5 z+)6fH-iRwtEC!p;tcEI3tnxNlMMp@dytkks<8v}8gE7_9^KBh6_2f0FoUm-!uW>V0pJb> zhGNC2hRQ!)i#K0dj~gq2S~=Z_qwiJ1V7{3ol89VM(iH?-5F~-P?dSa3A=}$^HE!Kf z?L6n!TOsCG&3M>PbTX2a$D>i_e0Q?=8oX8k}8328np*LdPJXwocPp<@<$Lq;PBjQFa zQt?ttVWp*#R>Im6B!vJh0=??OO-W6%XABS&0HsY$hGqr> zs@E0qWWlD@4Nr*;}J!@y3!?3#QTW_i+84QyA7R6M$! z?i7!$cmQq#@O}Vy1K0zz^;-hqhMI$=rdm2#k6X`GL;d1L999C=R6yKHw64d@o3Tcu zm;tbOO}1pKU|i}XP2M6Nop0DoRwGLg=PXhsM{w2_wg55&lKYF6diRKj+xp!?pC`v1 zL47dGj&+y>=rW9J`J*sV#*W->y&O{U=ytkaJUZAgy))A=B61IaTVcj-LNlybvlVHm z%|x#)wbbINdaS=)3F8;mqGT;li8dwKngN|?aHN@)sfiZ}gW|Tpyqyq)8L$Px7GNSU z0dNG76a+yK?bVZAu!(N&wf#E>GwMLeDfhWz#FaGaNVu*bWf6riy3>N`Zv6^Ogz++r zkR-UlM59A09^KB)5swZX5h=hVS`We`TMq!31u(*ZOqg|;uxP}rn~7GD<|I^T`iWkt z$J#&dC&8J`#IFVlN>lM{GvPCvu}>yCc|$rqIDP_57A(21XvYPcB3pp=6>Y2E6;{cS z#j-1h9DxBTN#re}qAkd?2o{lq$&of-1mankCCT>z%)^WZt-)9T-q1HsDjwa=&J&N< z;=ye34#GqsV*sWA>;o_aV0ZiH4$LQblrU5y(!3FA)l4)q!>L7Dtw%Zl-a7Ze020k8 zJJRa)1YAK{642)f%2|SJL6Qhw``i@Fl4B8OD|H?w!dPhk{5*gq7%{maBaAm96_0Lb z=ZnYdQG^kY5g5bfaR7ZVd6HoOJuro8eK3&>!9)X>lJ!uykUL$4S$`d&cc+&cf@1>MnpQUTAf;x5xo6Re}YMDc0__; zc13D1(ZmUuoW%mn?uf#LLFMU9@is`sBPAu}lKB5H9-tw3EKVQ*0000 Date: Mon, 8 May 2023 17:39:06 -0400 Subject: [PATCH 02/18] mergeback for 5.9.1-SNAPSHOT --- pom.xml | 2 +- score-client/pom.xml | 2 +- score-core/pom.xml | 2 +- score-fs/pom.xml | 2 +- score-server/pom.xml | 2 +- score-test/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 05104cd8..d66f44bb 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT pom ${project.artifactId} ${project.name} diff --git a/score-client/pom.xml b/score-client/pom.xml index 3afe0d24..6ebba856 100644 --- a/score-client/pom.xml +++ b/score-client/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT ../pom.xml diff --git a/score-core/pom.xml b/score-core/pom.xml index d4d7b19d..fe7e2fe2 100644 --- a/score-core/pom.xml +++ b/score-core/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT ../pom.xml diff --git a/score-fs/pom.xml b/score-fs/pom.xml index 46941fff..1f02ceb4 100644 --- a/score-fs/pom.xml +++ b/score-fs/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT ../pom.xml diff --git a/score-server/pom.xml b/score-server/pom.xml index 270ba868..aea560ad 100644 --- a/score-server/pom.xml +++ b/score-server/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT ../pom.xml diff --git a/score-test/pom.xml b/score-test/pom.xml index 059f1bca..84971215 100644 --- a/score-test/pom.xml +++ b/score-test/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.0 + 5.9.1-SNAPSHOT ../pom.xml From d78803f4c2640e3212da18c242598ddaaddea1ef Mon Sep 17 00:00:00 2001 From: Mitchell Shiell <59712867+MitchellShiell@users.noreply.github.com> Date: Wed, 10 May 2023 11:48:03 -0400 Subject: [PATCH 03/18] updated readme copy --- README.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 7f60dce2..08eb2701 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Score - Genomic File Transfer & Object Storage +# Score - File Transfer & Object Storage [](http://slack.overture.bio) [](https://github.com/overture-stack/score/blob/develop/LICENSE) @@ -8,7 +8,7 @@ score-logo -Genomics data volume and velocity have increased dramatically, rendering on-premise storage insufficient and demanding specialized software tools to manage these large and complex data sets in the cloud. [Score](https://www.overture.bio/documentation/score/) addresses this by facilitating the transfer and storage of genomics data to and from a distributed cloud network. +Genomics data volume and velocity have increased dramatically, rendering on-premise storage insufficient and demanding specialized software tools to manage data in the cloud. [Score](https://www.overture.bio/documentation/score/) addresses this by facilitating the transfer and storage of genomics data to and from a cloud network. @@ -17,9 +17,9 @@ Genomics data volume and velocity have increased dramatically, rendering on-prem > >

> ->
e +> > -> *Score is a vital service within the [Overture](https://www.overture.bio/) research software ecosystem. With our genomics data management solutions, scientists can significantly improve the lifecycle of their data and the quality of their research. See our [related products](#related-products) for more information on what Overture can offer.* +> *Score is a core component within the [Overture](https://www.overture.bio/) research software ecosystem. Overture is a toolkit of modular software components made to build into scalable genomics data management systems. See our [related products](#related-products) for more information on what Overture can offer.* > > @@ -36,9 +36,8 @@ Genomics data volume and velocity have increased dramatically, rendering on-prem ## Documentation -- See our Developer [wiki](https://github.com/overture-stack/score/wiki) -- For our user installation guide see our website [here](https://www.overture.bio/documentation/score/installation/installation/) -- For user guidance see our website [here](https://www.overture.bio/documentation/score/user-guide/admin-ui/) +- :construction: Developer documentation [Wiki](https://github.com/overture-stack/score/wiki) :construction: +- For user documentation, including installation, configuration and usage guides, can be found on our website [here](https://www.overture.bio/documentation/score/) ## Support & Contributions @@ -47,27 +46,26 @@ Genomics data volume and velocity have increased dramatically, rendering on-prem - Connect with us on [Slack](http://slack.overture.bio) - Add or Upvote a [feature request](https://github.com/overture-stack/score/issues?q=is%3Aopen+is%3Aissue+label%3Anew-feature+sort%3Areactions-%2B1-desc) -## Related Products +## Related Software
Overture overview
-Overture is an ecosystem of research software tools, each with narrow responsibilities, designed to address the changing needs of genomics research. +Score commonly works in tandem with our metadata service, [Song](https://github.com/overture-stack/SONG). While Score handles object storage and file transfer, Song validates and tracks all the associated file metadata. -Score commonly works in tandem with our metadata service, [Song](https://github.com/overture-stack/SONG). As Score facilitates object storage in the cloud, Song runs in parallel to validate and track files and associated metadata. +All our core microservices are included in the Overture **Data Management System** (DMS). Built from our core collection of microservices, the DMS offers turnkey installation, configuration, and deployment of Overture software. For more information on the DMS, read our [DMS documentation](https://www.overture.bio/documentation/dms/). -These tools are part of the Overture **Data Management System** (DMS), a fully functional and customizable data portal built from a packaged collection of Overtures microservices. For more information on DMS, read our [DMS documentation](https://www.overture.bio/documentation/dms/). - -See the links below for additional information on our other research software tools: +See the links below for information on our other research software tools:
-|Product|Description| +|Software|Description| |---|---| |[Ego](https://www.overture.bio/products/ego/)|An authorization and user management service| -|[Ego UI](https://www.overture.bio/products/ego-ui/)|A UI for managing EGO authentication and authorization services| -|[Score](https://www.overture.bio/products/score/)| Transfer data quickly and easily to and from any cloud-based storage system| -|[Song](https://www.overture.bio/products/song/)|Catalog and manage metadata of genomics data spread across cloud storage systems| +|[Ego UI](https://www.overture.bio/products/ego-ui/)|A UI for managing Ego authentication and authorization services| +|[Score](https://www.overture.bio/products/score/)| Transfer data to and from any cloud-based storage system| +|[Song](https://www.overture.bio/products/song/)|Catalog and manage metadata associated to file data spread across cloud storage systems| |[Maestro](https://www.overture.bio/products/maestro/)|Organizing your distributed data into a centralized Elasticsearch index| -|[Arranger](https://www.overture.bio/products/arranger/)|Organize an intuitive data search interface, complete with customizable components, tables, and search terms| \ No newline at end of file +|[Arranger](https://www.overture.bio/products/arranger/)|A search API with reusable UI components that build into configurable and functional data portals| +|[DMS-UI](https://github.com/overture-stack/dms-ui)|A simple web browser UI that integrates Ego and Arranger| \ No newline at end of file From 0f7ef4a238b36df84d7a224cd184dca032b9d87e Mon Sep 17 00:00:00 2001 From: Mitchell Shiell <59712867+MitchellShiell@users.noreply.github.com> Date: Wed, 10 May 2023 12:09:02 -0400 Subject: [PATCH 04/18] updated readme copy --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 08eb2701..1d15ca6e 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Genomics data volume and velocity have increased dramatically, rendering on-prem ## Documentation - :construction: Developer documentation [Wiki](https://github.com/overture-stack/score/wiki) :construction: -- For user documentation, including installation, configuration and usage guides, can be found on our website [here](https://www.overture.bio/documentation/score/) +- For user documentation, including installation, configuration and usage guides, see the Overture websites [Score documentation page](https://www.overture.bio/documentation/score/) ## Support & Contributions From 60f2840fb4c494bff4d4fb3aebe26f0089268abd Mon Sep 17 00:00:00 2001 From: Mitchell Shiell <59712867+MitchellShiell@users.noreply.github.com> Date: Thu, 11 May 2023 15:51:18 -0400 Subject: [PATCH 05/18] Update README.md Co-authored-by: Jon Eubank --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d15ca6e..6d3ac137 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ Genomics data volume and velocity have increased dramatically, rendering on-prem ## Documentation -- :construction: Developer documentation [Wiki](https://github.com/overture-stack/score/wiki) :construction: +- :construction: Developer documentation, including instructions for running Score from source can be found in the [Wiki](https://github.com/overture-stack/score/wiki) :construction: - For user documentation, including installation, configuration and usage guides, see the Overture websites [Score documentation page](https://www.overture.bio/documentation/score/) ## Support & Contributions From 9b257b4de89d6e4cec45d22b37253a23b9f3c176 Mon Sep 17 00:00:00 2001 From: dahiyaAD Date: Mon, 5 Jun 2023 17:08:54 -0400 Subject: [PATCH 06/18] CORS configurations for score server allowing multiple origins at once - #367 --- .../bio/overture/score/server/ServerMain.java | 18 ++++++++++++++++++ .../src/main/resources/application.yml | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/score-server/src/main/java/bio/overture/score/server/ServerMain.java b/score-server/src/main/java/bio/overture/score/server/ServerMain.java index 4cebb0ef..3c68171a 100644 --- a/score-server/src/main/java/bio/overture/score/server/ServerMain.java +++ b/score-server/src/main/java/bio/overture/score/server/ServerMain.java @@ -1,5 +1,6 @@ package bio.overture.score.server; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -7,6 +8,9 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * Application entry point. @@ -20,8 +24,22 @@ }) public class ServerMain { + @Value("${management.endpoints.web.cors.allowedOrigins}") + private String[] allowedOrigins; + public static void main(String... args) { SpringApplication.run(ServerMain.class, args); } + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins(allowedOrigins) + .allowedMethods("PUT", "DELETE", "GET", "POST"); + } + }; + } } \ No newline at end of file diff --git a/score-server/src/main/resources/application.yml b/score-server/src/main/resources/application.yml index 4f1e0e39..fe07430b 100644 --- a/score-server/src/main/resources/application.yml +++ b/score-server/src/main/resources/application.yml @@ -82,6 +82,13 @@ auth: # E.g. TIMEOUT(n) = TIMEOUT(n-1) * MULTIPLIER multiplier: 2.0 +#allowedOrigins can be configured to contain multiple values, all separated by commas +management: + endpoints: + web: + cors: + allowedOrigins: http://localhost:8081 + --- ############################################################################### From 3c8a3f549addcd3815dd88043e51782cefc34a41 Mon Sep 17 00:00:00 2001 From: dahiyaAD Date: Tue, 6 Jun 2023 11:12:00 -0400 Subject: [PATCH 07/18] Organizing score-server application.yml --- .../src/main/java/bio/overture/score/server/ServerMain.java | 2 +- score-server/src/main/resources/application.yml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/score-server/src/main/java/bio/overture/score/server/ServerMain.java b/score-server/src/main/java/bio/overture/score/server/ServerMain.java index 3c68171a..88c46202 100644 --- a/score-server/src/main/java/bio/overture/score/server/ServerMain.java +++ b/score-server/src/main/java/bio/overture/score/server/ServerMain.java @@ -24,7 +24,7 @@ }) public class ServerMain { - @Value("${management.endpoints.web.cors.allowedOrigins}") + @Value("${server.cors.allowedOrigins}") private String[] allowedOrigins; public static void main(String... args) { diff --git a/score-server/src/main/resources/application.yml b/score-server/src/main/resources/application.yml index fe07430b..a17920bd 100644 --- a/score-server/src/main/resources/application.yml +++ b/score-server/src/main/resources/application.yml @@ -27,7 +27,9 @@ server: compression: enabled: true mime-types: application/json - + #allowedOrigins can be configured to contain multiple values, all separated by commas + cors: + allowedOrigins: http://localhost:8081 s3: secured: true sigV4Enabled: true From d4489fb3ebb65c0ef20327b0bf0a9ef7ab374982 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Mon, 6 Nov 2023 09:30:24 -0500 Subject: [PATCH 08/18] docker JRE ireplacing JRE alpine image to support multiple architecturesmage multi arch supported --- Dockerfile | 12 ++++++------ Dockerfile.dev | 8 ++++---- Makefile | 5 ++--- docker/ego-init/init.sql | 6 +++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index 703a340d..19961f0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ ############################### # Maven builder ############################### -# -alpine-slim image does not support --release flag -FROM adoptopenjdk/openjdk11:jdk-11.0.6_10-alpine-slim as builder +# multi arch image including amd64, arm64, ... +FROM adoptopenjdk/openjdk11:jre-11.0.6_10 as builder ENV SERVER_JAR_FILE /score-server.jar ENV CLIENT_DIST_DIR /score-client-dist @@ -33,7 +33,7 @@ RUN cd score-client/target \ ############################### # Score Client ############################### -FROM ubuntu:18.04 as client +FROM --platform=linux/amd64 ubuntu:18.04 as client ENV CLIENT_DIST_DIR /score-client-dist ENV JDK_DOWNLOAD_URL https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz @@ -76,7 +76,7 @@ WORKDIR $SCORE_CLIENT_HOME ############################### # Score Server ############################### -FROM adoptopenjdk/openjdk11:jre-11.0.6_10-alpine as server +FROM adoptopenjdk/openjdk11:jre-11.0.6_10 as server # Paths ENV SCORE_HOME /score-server @@ -86,8 +86,8 @@ ENV SCORE_USER score ENV SCORE_UID 9999 ENV SCORE_GID 9999 -RUN addgroup -S -g $SCORE_GID $SCORE_USER \ - && adduser -S -u $SCORE_UID -G $SCORE_USER $SCORE_USER \ +RUN addgroup --system --gid $SCORE_GID $SCORE_USER \ + && adduser --system --uid $SCORE_UID --ingroup $SCORE_USER $SCORE_USER \ && mkdir $SCORE_HOME $SCORE_LOGS \ && chown -R $SCORE_UID:$SCORE_GID $SCORE_HOME diff --git a/Dockerfile.dev b/Dockerfile.dev index d4a6d101..106662d9 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,7 +1,7 @@ ############################### # Score Client ############################### -FROM ubuntu:18.04 as client +FROM --platform=linux/amd64 ubuntu:18.04 as client ENV CLIENT_DIST_DIR /score-client-dist ENV JDK_DOWNLOAD_URL https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz @@ -54,7 +54,7 @@ WORKDIR $SCORE_CLIENT_HOME ############################### # Score Server ############################### -FROM adoptopenjdk/openjdk11:jre-11.0.6_10-alpine as server +FROM adoptopenjdk/openjdk11:jre-11.0.6_10 as server # Paths ENV SCORE_HOME /score-server @@ -64,8 +64,8 @@ ENV SCORE_USER score ENV SCORE_UID 9999 ENV SCORE_GID 9999 -RUN addgroup -S -g $SCORE_GID $SCORE_USER \ - && adduser -S -u $SCORE_UID -G $SCORE_USER $SCORE_USER \ +RUN addgroup --system --gid $SCORE_GID $SCORE_USER \ + && adduser --system --uid $SCORE_UID --ingroup $SCORE_USER $SCORE_USER \ && mkdir $SCORE_HOME $SCORE_LOGS \ && chown -R $SCORE_UID:$SCORE_GID $SCORE_HOME diff --git a/Makefile b/Makefile index 79189776..c6ee7bd7 100644 --- a/Makefile +++ b/Makefile @@ -60,7 +60,6 @@ _ping_score_server: @echo $(YELLOW)$(INFO_HEADER) "Pinging score-server on http://localhost:8087" $(END) @$(RETRY_CMD) curl \ -XGET \ - -H 'Authorization: Bearer f69b726d-d40f-4261-b105-1ec7e6bf04d5' \ 'http://localhost:8087/download/ping' @echo "" @@ -210,8 +209,8 @@ log-score-server: # Display logs for score-client log-score-client: - @echo $(YELLOW)$(INFO_HEADER) "Displaying logs for score-server" $(END) - @$(DOCKER_COMPOSE_CMD) logs score-server + @echo $(YELLOW)$(INFO_HEADER) "Displaying logs for score-client" $(END) + @$(DOCKER_COMPOSE_CMD) logs score-client ############################################################# diff --git a/docker/ego-init/init.sql b/docker/ego-init/init.sql index c541a2a8..d2ad8b74 100644 --- a/docker/ego-init/init.sql +++ b/docker/ego-init/init.sql @@ -372,9 +372,9 @@ ed5149c4-d8c3-46f8-ab01-b903f82b5fe3 \N score.TEST-CA -- COPY public.token (id, name, owner, issuedate, isrevoked, description, expirydate) FROM stdin; -f7d708ef-41f8-493f-ad8e-cb0ac97b0688 f69b726d-d40f-4261-b105-1ec7e6bf04d5 c6608c3e-1181-4957-99c4-094493391096 2019-11-20 20:52:08.247 f \N 2020-11-19 20:52:08.247 -fafaac34-6b01-47ef-9ae6-6d8cb30af5ca fd0c6c40-254b-4a5f-82e7-cf21a380ccb3 c6608c3e-1181-4957-99c4-094493391096 2019-11-20 20:55:56.186 f \N 2020-11-19 20:55:56.186 -7df26ca6-801f-4302-a318-6f766d759b1d 1f070fb0-0ee4-4815-8097-b5b065c661cc c6608c3e-1181-4957-99c4-094493391096 2019-11-20 20:57:38.345 f \N 2020-11-19 20:57:38.345 +f7d708ef-41f8-493f-ad8e-cb0ac97b0688 f69b726d-d40f-4261-b105-1ec7e6bf04d5 c6608c3e-1181-4957-99c4-094493391096 2023-11-02 20:52:08.247 f \N 2030-11-02 20:52:08.247 +fafaac34-6b01-47ef-9ae6-6d8cb30af5ca fd0c6c40-254b-4a5f-82e7-cf21a380ccb3 c6608c3e-1181-4957-99c4-094493391096 2023-11-02 20:55:56.186 f \N 2030-11-02 20:55:56.186 +7df26ca6-801f-4302-a318-6f766d759b1d 1f070fb0-0ee4-4815-8097-b5b065c661cc c6608c3e-1181-4957-99c4-094493391096 2023-11-02 20:57:38.345 f \N 2030-11-02 20:57:38.345 \. From 21975fd4e83aaa3f5bb01b50f1f377d6ea19ce06 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Mon, 6 Nov 2023 11:19:48 -0500 Subject: [PATCH 09/18] latest ubuntu LTS 22.04 score client --- Dockerfile | 2 +- Dockerfile.dev | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 19961f0b..26751d87 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN cd score-client/target \ ############################### # Score Client ############################### -FROM --platform=linux/amd64 ubuntu:18.04 as client +FROM --platform=linux/amd64 ubuntu:22.04 as client ENV CLIENT_DIST_DIR /score-client-dist ENV JDK_DOWNLOAD_URL https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz diff --git a/Dockerfile.dev b/Dockerfile.dev index 106662d9..8f3e6f0b 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,7 +1,7 @@ ############################### # Score Client ############################### -FROM --platform=linux/amd64 ubuntu:18.04 as client +FROM --platform=linux/amd64 ubuntu:22.04 as client ENV CLIENT_DIST_DIR /score-client-dist ENV JDK_DOWNLOAD_URL https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz From 81d5eb5891a72393415d1274f82332c3010574ef Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Wed, 8 Nov 2023 13:26:00 -0500 Subject: [PATCH 10/18] using JDK image as builder --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 26751d87..39d6cd14 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ ############################### # Maven builder ############################### -# multi arch image including amd64, arm64, ... -FROM adoptopenjdk/openjdk11:jre-11.0.6_10 as builder +# JDK image as builder +FROM adoptopenjdk/openjdk11:jdk-11.0.6_10-slim as builder ENV SERVER_JAR_FILE /score-server.jar ENV CLIENT_DIST_DIR /score-client-dist From bed4ba8fb2b7765037c871f298b052fdf3ee50fc Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Fri, 10 Nov 2023 09:27:31 -0500 Subject: [PATCH 11/18] update docker dind (#376) from docker image docker:18.06-dind to docker:20.10-dind --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ad5c26d3..d31e7e79 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,7 +36,7 @@ spec: - name: maven-cache mountPath: "/root/.m2" - name: dind-daemon - image: docker:18.06-dind + image: docker:20.10-dind securityContext: privileged: true runAsUser: 0 @@ -49,7 +49,7 @@ spec: - cat tty: true - name: docker - image: docker:18-git + image: docker:20-git tty: true env: - name: DOCKER_HOST From 06799f67c7371a7dd8071553ac55bc9d86711647 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Tue, 14 Nov 2023 18:45:12 -0500 Subject: [PATCH 12/18] fix docker dind TLS (#379) --- Jenkinsfile | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index d31e7e79..670db3d7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,19 +30,26 @@ spec: tty: true image: openjdk:11 env: - - name: DOCKER_HOST - value: tcp://localhost:2375 + - name: DOCKER_TLS_VERIFY + value: 1 + - name: DOCKER_CERT_PATH + value: /var/lib/docker/tls/client volumeMounts: + - name: docker-graph-storage + mountPath: /var/lib/docker - name: maven-cache mountPath: "/root/.m2" - name: dind-daemon image: docker:20.10-dind securityContext: - privileged: true - runAsUser: 0 + privileged: true + runAsUser: 0 volumeMounts: - name: docker-graph-storage mountPath: /var/lib/docker + env: + - name: DOCKER_TLS_CERTDIR + value: /var/lib/docker/tls - name: helm image: alpine/helm:2.12.3 command: @@ -52,10 +59,15 @@ spec: image: docker:20-git tty: true env: - - name: DOCKER_HOST - value: tcp://localhost:2375 - name: HOME value: /home/jenkins/agent + - name: DOCKER_TLS_VERIFY + value: 1 + - name: DOCKER_CERT_PATH + value: /var/lib/docker/tls/client + volumeMounts: + - name: docker-graph-storage + mountPath: /var/lib/docker - name: curl image: curlimages/curl command: From f915e6c48ff9202d9676766096e34b529b6a98e7 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Wed, 15 Nov 2023 14:11:26 -0500 Subject: [PATCH 13/18] increase Jenkins timeout (#380) from 30 to 45 mins --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 670db3d7..d2d7ba96 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -104,7 +104,7 @@ pipeline { } options { - timeout(time: 30, unit: 'MINUTES') + timeout(time: 45, unit: 'MINUTES') timestamps() } From 67a7cb512e83a1ebe0202342e09b45a29d3e5987 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Thu, 16 Nov 2023 13:11:13 -0500 Subject: [PATCH 14/18] Fix/jenkins extend timeout (#381) * increase Jenkins timeout from 30 to 45 mins * increase Jenkins timeout from 45 to 60 mins * increase jenkins timeout --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index d2d7ba96..5d6e5c66 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -104,7 +104,7 @@ pipeline { } options { - timeout(time: 45, unit: 'MINUTES') + timeout(time: 2, unit: 'HOURS') timestamps() } From 1597035d2fb7552ae0bb749bfe1b8360fd1a2452 Mon Sep 17 00:00:00 2001 From: Leonardo Rivera Date: Thu, 16 Nov 2023 15:15:24 -0500 Subject: [PATCH 15/18] update DeployWithHelm job name in Jenkinsfile (#383) --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5d6e5c66..048dbe32 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -266,7 +266,7 @@ pipeline { } } steps { - build(job: '/Overture.bio/provision/helm', parameters: [ + build(job: '/Overture.bio/provision/DeployWithHelm', parameters: [ [$class: 'StringParameterValue', name: 'OVERTURE_ENV', value: 'qa' ], [$class: 'StringParameterValue', name: 'OVERTURE_CHART_NAME', value: 'score'], [$class: 'StringParameterValue', name: 'OVERTURE_RELEASE_NAME', value: 'score'], @@ -283,7 +283,7 @@ pipeline { branch 'master' } steps { - build(job: '/Overture.bio/provision/helm', parameters: [ + build(job: '/Overture.bio/provision/DeployWithHelm', parameters: [ [$class: 'StringParameterValue', name: 'OVERTURE_ENV', value: 'staging' ], [$class: 'StringParameterValue', name: 'OVERTURE_CHART_NAME', value: 'score'], [$class: 'StringParameterValue', name: 'OVERTURE_RELEASE_NAME', value: 'score'], From 11337b520545a202f60ed636224aefc87d83640f Mon Sep 17 00:00:00 2001 From: Ummulkiram <57347898+UmmulkiramR@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:35:25 -0500 Subject: [PATCH 16/18] fix for issue #385 (#386) Co-authored-by: UmmulkiramR --- .../server/repository/azure/AzureDownloadService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/score-server/src/main/java/bio/overture/score/server/repository/azure/AzureDownloadService.java b/score-server/src/main/java/bio/overture/score/server/repository/azure/AzureDownloadService.java index c37fbc32..8ebfbafa 100644 --- a/score-server/src/main/java/bio/overture/score/server/repository/azure/AzureDownloadService.java +++ b/score-server/src/main/java/bio/overture/score/server/repository/azure/AzureDownloadService.java @@ -43,6 +43,7 @@ import java.net.URISyntaxException; import java.util.Base64; import java.util.List; +import java.util.Objects; import static com.google.common.base.Preconditions.checkArgument; @@ -101,7 +102,12 @@ public ObjectSpecification download(String objectId, long offset, long length, b } fillPartUrls(objectId, parts); - val md5 = base64ToHexMD5(blob.getProperties().getContentMD5()); + String contentMd5 = blob.getProperties().getContentMD5(); + String md5 = null; + if(Objects.nonNull(contentMd5)) { + md5 = base64ToHexMD5(contentMd5); + } + return new ObjectSpecification(objectId, objectId, objectId, parts, rangeLength, md5, false); } catch (StorageException e) { log.error("Failed to download objectId: {}, offset: {}, length: {}, forExternalUse: {}: {} ", From 7c2fdce54b20367dbf12194957b94315392ebce5 Mon Sep 17 00:00:00 2001 From: Ummulkiram <57347898+UmmulkiramR@users.noreply.github.com> Date: Fri, 24 Nov 2023 12:14:49 -0500 Subject: [PATCH 17/18] Auto sync storage profiles #378 (#382) * added server endpoint to get profiles * change to switch score-client storage implementations * cleared azure and s3 related entries app.yml * some bug fixes and enhancements * updated comment * added test profile. * added test profile. * refactored code based on review comments - BaseController now returns a single profile value. The actual profile name and the profile value returned by the api are now different. * debug logging removed * replaced profile value * updated readme * updated readme * added a test profile * review changes - Storage profile values now come from an enum in score-core - test configuration created to mock storage profile bean - users will be able to provide a default profile value when working with old score-server instances * users will be able to provide a default profile value when working with old score-server instances * config change * added a test config in score server --------- Co-authored-by: UmmulkiramR --- score-client/README.md | 7 +- .../score/client/command/UploadCommand.java | 15 +- .../score/client/config/AzureConfig.java | 13 +- .../score/client/config/ProfileConfig.java | 72 ++++++++++ .../score/client/config/S3Config.java | 11 +- .../client/download/DownloadStateStore.java | 11 +- .../upload/azure/AzureUploadService.java | 1 + .../client/upload/s3/S3UploadService.java | 1 + .../overture/score/client/util/BeanUtil.java | 31 +++++ .../src/main/resources/application.yml | 61 +-------- .../overture/score/client/ClientMainTest.java | 2 + .../client/config/TestProfileConfig.java | 26 ++++ .../src/test/resources/application.yml | 129 ++++++++++++++++++ .../score/core/model/StorageProfiles.java | 33 +++++ .../score/server/config/ProfileConfig.java | 26 ++++ .../server/controller/BaseController.java | 27 ++++ .../server/config/TestProfileConfig.java | 19 +++ 17 files changed, 411 insertions(+), 74 deletions(-) create mode 100644 score-client/src/main/java/bio/overture/score/client/config/ProfileConfig.java create mode 100644 score-client/src/main/java/bio/overture/score/client/util/BeanUtil.java create mode 100644 score-client/src/test/java/bio/overture/score/client/config/TestProfileConfig.java create mode 100644 score-client/src/test/resources/application.yml create mode 100644 score-core/src/main/java/bio/overture/score/core/model/StorageProfiles.java create mode 100644 score-server/src/main/java/bio/overture/score/server/config/ProfileConfig.java create mode 100644 score-server/src/main/java/bio/overture/score/server/controller/BaseController.java create mode 100644 score-server/src/test/java/bio/overture/score/server/config/TestProfileConfig.java diff --git a/score-client/README.md b/score-client/README.md index 3e5d1590..fedec157 100644 --- a/score-client/README.md +++ b/score-client/README.md @@ -78,5 +78,10 @@ To enable logging of request bodies and headers, append the following to the com `--logging.level.org.apache.http=DEBUG` ## Azure -For azure support, use the `azure` profile. Block sizes for uploads + +Score-client dynamically loads storage profile specific implementations (currently S3 or Azure) based on the profile score-server is running on. +It does this by calling an endpoint on score-server to fetch the active storage profiles. +For older score-server versions where the profile endpoint isn't available, the score-client will use the default (S3) storage profile implementation. +This eliminates the need for users to ensure that score-client is running on a profile compatible with score-server. + can be configured with the `azure.blockSize` property. \ No newline at end of file diff --git a/score-client/src/main/java/bio/overture/score/client/command/UploadCommand.java b/score-client/src/main/java/bio/overture/score/client/command/UploadCommand.java index 926c2421..c1481355 100644 --- a/score-client/src/main/java/bio/overture/score/client/command/UploadCommand.java +++ b/score-client/src/main/java/bio/overture/score/client/command/UploadCommand.java @@ -23,14 +23,17 @@ import bio.overture.score.client.manifest.ManifestService; import bio.overture.score.client.manifest.UploadManifest; import bio.overture.score.client.upload.UploadService; +import bio.overture.score.client.util.BeanUtil; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import lombok.extern.slf4j.Slf4j; import lombok.val; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -64,9 +67,19 @@ public class UploadCommand extends RepositoryAccessCommand { */ @Autowired private ManifestService manifestService; - @Autowired private UploadService uploader; + @Autowired + ApplicationContext appContext; + + @Autowired + private BeanUtil beanUtil; + + @PostConstruct + public void initializeStorageProfile() throws Exception{ + uploader = (UploadService) beanUtil.getBeanForProfile(UploadService.class); + } + @Override public int execute() throws Exception { checkParameter(objectId != null || manifestResource != null, "One of --object-id or --manifest must be specified"); diff --git a/score-client/src/main/java/bio/overture/score/client/config/AzureConfig.java b/score-client/src/main/java/bio/overture/score/client/config/AzureConfig.java index 4ee838df..bd3a09b3 100644 --- a/score-client/src/main/java/bio/overture/score/client/config/AzureConfig.java +++ b/score-client/src/main/java/bio/overture/score/client/config/AzureConfig.java @@ -19,24 +19,19 @@ import bio.overture.score.client.upload.UploadService; import bio.overture.score.client.upload.azure.AzureUploadService; +import bio.overture.score.client.upload.s3.S3UploadService; import bio.overture.score.client.util.AzurePresignedUrlValidator; import bio.overture.score.client.util.PresignedUrlValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +// Note: Name the beans as profile-name+class-type to be able to dynamically fetch beans at runtime based on score-server profiles @Configuration -@Profile("azure") public class AzureConfig { @Bean - public UploadService uploadService() { - return new AzureUploadService(); - } - + public UploadService azUploadService(){ return new AzureUploadService();} @Bean - public PresignedUrlValidator urlValidator() { - return new AzurePresignedUrlValidator(); - } - + public AzurePresignedUrlValidator azPresignedUrlValidator(){return new AzurePresignedUrlValidator();} } diff --git a/score-client/src/main/java/bio/overture/score/client/config/ProfileConfig.java b/score-client/src/main/java/bio/overture/score/client/config/ProfileConfig.java new file mode 100644 index 00000000..334e60da --- /dev/null +++ b/score-client/src/main/java/bio/overture/score/client/config/ProfileConfig.java @@ -0,0 +1,72 @@ +package bio.overture.score.client.config; + +import bio.overture.score.client.exception.NotRetryableException; +import bio.overture.score.core.model.StorageProfiles; +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import lombok.val; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.web.client.RestTemplate; + +@Configuration +@Slf4j +@ConditionalOnProperty(value="isTest", havingValue="false") +public class ProfileConfig { + + @Autowired + private RestTemplate serviceTemplate; + + @Value("${storage.url}") + @NonNull + private String endpoint; + + @Autowired + @Value("${defaultProfile:collaboratory}") + private String defaultProfile; + + @Autowired + @Value("${isTest}") + private boolean isTest = false; + + @Qualifier("clientVersion") + @Autowired + @NonNull + String clientVersion; + + @Bean + public String storageProfile(){ + String profile = getStorageProfile(); + return profile; + } + + private String getStorageProfile() { + log.debug("get profile endpoint: "+endpoint); + try{ + String storageProfile = serviceTemplate.exchange(endpoint + "/profile", HttpMethod.GET, defaultEntity(), String.class).getBody(); + return storageProfile; + }catch(NotRetryableException nre ){ + log.error("received exception when getting profiles: " + nre.getMessage()); + } + return StorageProfiles.getProfileValue(defaultProfile); + } + + + private HttpEntity defaultEntity() { + return new HttpEntity(defaultHeaders()); + } + + private HttpHeaders defaultHeaders() { + val requestHeaders = new HttpHeaders(); + requestHeaders.add(HttpHeaders.USER_AGENT, clientVersion); + return requestHeaders; + } + +} diff --git a/score-client/src/main/java/bio/overture/score/client/config/S3Config.java b/score-client/src/main/java/bio/overture/score/client/config/S3Config.java index ca0b873f..3e34c95d 100644 --- a/score-client/src/main/java/bio/overture/score/client/config/S3Config.java +++ b/score-client/src/main/java/bio/overture/score/client/config/S3Config.java @@ -19,24 +19,21 @@ import bio.overture.score.client.upload.UploadService; import bio.overture.score.client.upload.s3.S3UploadService; +import bio.overture.score.client.util.AzurePresignedUrlValidator; import bio.overture.score.client.util.PresignedUrlValidator; import bio.overture.score.client.util.S3PresignedUrlValidator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +// Note: Name the beans as profile-name+class-type to be able to dynamically fetch beans at runtime based on score-server profiles @Configuration -@Profile({ "!azure" }) public class S3Config { @Bean - public UploadService uploadService() { - return new S3UploadService(); - } - + public UploadService s3UploadService(){return new S3UploadService();} @Bean - public PresignedUrlValidator urlValidator() { + public S3PresignedUrlValidator s3PresignedUrlValidator(){ return new S3PresignedUrlValidator(); } - } diff --git a/score-client/src/main/java/bio/overture/score/client/download/DownloadStateStore.java b/score-client/src/main/java/bio/overture/score/client/download/DownloadStateStore.java index 4842224f..3200efe9 100644 --- a/score-client/src/main/java/bio/overture/score/client/download/DownloadStateStore.java +++ b/score-client/src/main/java/bio/overture/score/client/download/DownloadStateStore.java @@ -19,6 +19,7 @@ import bio.overture.score.client.exception.NotRetryableException; import bio.overture.score.client.state.TransferState; +import bio.overture.score.client.util.BeanUtil; import bio.overture.score.client.util.PresignedUrlValidator; import bio.overture.score.core.model.ObjectSpecification; import bio.overture.score.core.model.Part; @@ -27,6 +28,7 @@ import lombok.val; import org.springframework.beans.factory.annotation.Autowired; +import javax.annotation.PostConstruct; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -35,11 +37,16 @@ @Slf4j public class DownloadStateStore extends TransferState { - @Autowired private PresignedUrlValidator urlValidator; - + @Autowired + private BeanUtil beanUtil; private static final ObjectMapper MAPPER = new ObjectMapper(); + @PostConstruct + public void initializeStorageProfile() throws Exception{ + urlValidator = (PresignedUrlValidator) beanUtil.getBeanForProfile(PresignedUrlValidator.class); + } + public void init(File stateDir, ObjectSpecification spec) { log.debug("Download Specification : {}", spec); try { diff --git a/score-client/src/main/java/bio/overture/score/client/upload/azure/AzureUploadService.java b/score-client/src/main/java/bio/overture/score/client/upload/azure/AzureUploadService.java index b5473ef9..855b4500 100644 --- a/score-client/src/main/java/bio/overture/score/client/upload/azure/AzureUploadService.java +++ b/score-client/src/main/java/bio/overture/score/client/upload/azure/AzureUploadService.java @@ -54,6 +54,7 @@ public class AzureUploadService implements UploadService { @Override public void upload(File file, String objectId, String md5, boolean redo) throws IOException { + log.debug("Initiating azure upload"); // Get object specification from server val spec = storageService.initiateUpload(objectId, file.length(), redo, md5); diff --git a/score-client/src/main/java/bio/overture/score/client/upload/s3/S3UploadService.java b/score-client/src/main/java/bio/overture/score/client/upload/s3/S3UploadService.java index 61ac941b..a3e1d2e8 100644 --- a/score-client/src/main/java/bio/overture/score/client/upload/s3/S3UploadService.java +++ b/score-client/src/main/java/bio/overture/score/client/upload/s3/S3UploadService.java @@ -80,6 +80,7 @@ public void setup() { */ @Override public void upload(File file, String objectId, String md5, final boolean redo) throws IOException { + log.debug("Initiating S3 upload"); boolean tryAgain = redo; for (int retry = 0; retry < retryNumber; retry++) try { diff --git a/score-client/src/main/java/bio/overture/score/client/util/BeanUtil.java b/score-client/src/main/java/bio/overture/score/client/util/BeanUtil.java new file mode 100644 index 00000000..39901657 --- /dev/null +++ b/score-client/src/main/java/bio/overture/score/client/util/BeanUtil.java @@ -0,0 +1,31 @@ +package bio.overture.score.client.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + + +// utility class to inject beans dynamically at runtime + +@Component +public class BeanUtil { + + @Autowired + ApplicationContext appContext; + + //this method injects beans dynamically based on score-server active profile + public Object getBeanForProfile(Class cl){ + String profile = appContext.getBean("storageProfile", String.class); + + Set beans = appContext.getBeansOfType(cl).keySet(); + return appContext.getBean(beans.stream() + .filter(s -> s.equals(profile+cl.getSimpleName())) + .collect(Collectors.toList()) + .get(0), cl); + } +} diff --git a/score-client/src/main/resources/application.yml b/score-client/src/main/resources/application.yml index cc9b8d28..331e3612 100644 --- a/score-client/src/main/resources/application.yml +++ b/score-client/src/main/resources/application.yml @@ -76,42 +76,9 @@ mount: token: public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlvqX7PDezX7BC0yc14zwJw2qgs5KDyZZvEeNowHCgHLcCtCVZ2JIx+ccUPp1FVudfZpLoboZ3RjT+6oOPHpNilXqUZfT81acCVHhvyJe7FNxdUWKpIIVKM/8bJj1pVkst0YHLBJ3KojZYJCMNUxUkyHM+yGrn9tmSdFBmwJnBLTkSxOrS2bvuZvkjERnoQJCoTm2XBKoCOzEuVPjIeB2KiFcNqiZwhjnCSQGPmg7fyJfQt1vMl+8RST3IXxphf8KKaWMl0rTXQhIHYL23P/tvC2lpJgx0rzgnxkAgFSrCxLstIklFAAg+j7ykivOyynIlCfXGv4cPTq5UqvIB8MBRQIDAQAB ---- - -############################################################################### -# Profile - "aws" -############################################################################### - -spring.profiles: aws - -storage: - url: https://virginia.cloud.icgc.org - -metadata: - url: https://virginia.song.icgc.org - ssl: - enabled: true - -client: - ssl: - custom: false - ---- - -############################################################################### -# Profile - "azure" -############################################################################### - -spring.profiles: azure -storage: - url: https://score.azure.icgc.overture.bio - -metadata: - url: https://song.azure.icgc.overture.bio - -azure: - blockSize: 104857600 +isTest: false +defaultProfile: collaboratory --- @@ -132,25 +99,6 @@ client: --- -############################################################################### -# Profile - "collab" -############################################################################### - -spring.profiles: collab - -# Storage server -storage: - url: https://storage.cancercollaboratory.org - -metadata: - url: https://song.cancercollaboratory.org - -client: - ssl: - custom: false - ---- - ############################################################################### # Profile - "oicr" ############################################################################### @@ -174,3 +122,8 @@ logging: springframework.retry: DEBUG springframework.web: DEBUG com.amazonaws.services: DEBUG + +--- +############################################################################### +# Profile - "debug" +############################################################################### diff --git a/score-client/src/test/java/bio/overture/score/client/ClientMainTest.java b/score-client/src/test/java/bio/overture/score/client/ClientMainTest.java index 126ab337..31a4533a 100644 --- a/score-client/src/test/java/bio/overture/score/client/ClientMainTest.java +++ b/score-client/src/test/java/bio/overture/score/client/ClientMainTest.java @@ -23,6 +23,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.springframework.test.context.ActiveProfiles; import java.io.File; import java.util.UUID; @@ -31,6 +32,7 @@ import static org.junit.Assert.assertTrue; @Slf4j +@ActiveProfiles("test") public class ClientMainTest extends AbstractClientMainTest { @Rule diff --git a/score-client/src/test/java/bio/overture/score/client/config/TestProfileConfig.java b/score-client/src/test/java/bio/overture/score/client/config/TestProfileConfig.java new file mode 100644 index 00000000..de2e8dba --- /dev/null +++ b/score-client/src/test/java/bio/overture/score/client/config/TestProfileConfig.java @@ -0,0 +1,26 @@ +package bio.overture.score.client.config; + +import bio.overture.score.client.exception.NotRetryableException; +import bio.overture.score.core.model.StorageProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.test.context.ContextConfiguration; + +@TestConfiguration +public class TestProfileConfig { + + @Autowired + @Value("${defaultProfile:collaboratory}") + private String defaultProfile; + + @Bean + public String storageProfile(){ + return StorageProfiles.getProfileValue(defaultProfile); + } + +} diff --git a/score-client/src/test/resources/application.yml b/score-client/src/test/resources/application.yml new file mode 100644 index 00000000..bed661c5 --- /dev/null +++ b/score-client/src/test/resources/application.yml @@ -0,0 +1,129 @@ +# +# Copyright (c) 2016 The Ontario Institute for Cancer Research. All rights reserved. +# +# This program and the accompanying materials are made available under the terms of the GNU Public License v3.0. +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# SCORE Client - Configuration +# + +############################################################################### +# Profile - common +############################################################################### + +client: + ansi: ${ansi:true} + silent: ${silent:false} + quiet: ${quiet:false} + accessToken: "${accessToken:}" # Alias for backwards compatibility + connectTimeoutSeconds: 60 + readTimeoutSeconds: 60 + # path of dir with WRITE access for score client upload state files + # if empty uses parent dir of current file to upload + uploadStateDir: "" + + ssl: + custom: false + +kfportal: + url: https://arranger.kids-first.io/june_13/graphql + +kf: + token: + url: https://v2i1r42t6d.execute-api.us-east-1.amazonaws.com/beta/token + download: + url: https://data.kidsfirstdrc.org + partSize: 1073741824 + expiration: 86400 + +transport: + fileFrom: memory + memory: 1 + parallel: 6 + +storage: + # default for backwards compatibility + url: https://virginia.cloud.icgc.org + retryNumber: 10 + retryTimeout: 1 + +metadata: + # default for backwards compatibility + url: https://virginia.song.icgc.org + ssl: + enabled: true + +portal: + url: https://dcc.icgc.org + +logging: + file: target/logs/client.log + +mount: + logging: false + +token: + public-key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlvqX7PDezX7BC0yc14zwJw2qgs5KDyZZvEeNowHCgHLcCtCVZ2JIx+ccUPp1FVudfZpLoboZ3RjT+6oOPHpNilXqUZfT81acCVHhvyJe7FNxdUWKpIIVKM/8bJj1pVkst0YHLBJ3KojZYJCMNUxUkyHM+yGrn9tmSdFBmwJnBLTkSxOrS2bvuZvkjERnoQJCoTm2XBKoCOzEuVPjIeB2KiFcNqiZwhjnCSQGPmg7fyJfQt1vMl+8RST3IXxphf8KKaWMl0rTXQhIHYL23P/tvC2lpJgx0rzgnxkAgFSrCxLstIklFAAg+j7ykivOyynIlCfXGv4cPTq5UqvIB8MBRQIDAQAB + + +isTest: true +defaultProfile: collaboratory + +--- + +############################################################################### +# Profile - "kf" +############################################################################### + +spring.profiles: kf + +# Storage server +storage: + url: https://kf.com + + +client: + ssl: + custom: false + +--- + +############################################################################### +# Profile - "oicr" +############################################################################### + +spring.profiles: oicr + +# uses storage.url and client.ssl.custom define in common + + +--- + +############################################################################### +# Profile - "debug" +############################################################################### + +spring.profiles: debug + +logging: + level: + org.icgc.dcc.storage: DEBUG + springframework.retry: DEBUG + springframework.web: DEBUG + com.amazonaws.services: DEBUG + +--- +############################################################################### +# Profile - "debug" +############################################################################### diff --git a/score-core/src/main/java/bio/overture/score/core/model/StorageProfiles.java b/score-core/src/main/java/bio/overture/score/core/model/StorageProfiles.java new file mode 100644 index 00000000..5065673d --- /dev/null +++ b/score-core/src/main/java/bio/overture/score/core/model/StorageProfiles.java @@ -0,0 +1,33 @@ +package bio.overture.score.core.model; + +import java.util.HashSet; +import java.util.Set; + +public enum StorageProfiles { + + AZURE( "azure","az"), + COLLABORATORY( "collaboratory","s3"); + + + + private final String profileKey; + private final String profileValue; + + StorageProfiles(String profileKey, String profileValue) { + this.profileKey = profileKey; + this.profileValue=profileValue; + } + + public static String getProfileValue(String key){ + return StorageProfiles.valueOf(key.toUpperCase()).profileValue; + } + + public static Set keySet(){ + Set valueSet = new HashSet<>(); + for ( StorageProfiles st : StorageProfiles.values()){ + valueSet.add(st.profileKey); + } + return valueSet; + } + +} diff --git a/score-server/src/main/java/bio/overture/score/server/config/ProfileConfig.java b/score-server/src/main/java/bio/overture/score/server/config/ProfileConfig.java new file mode 100644 index 00000000..0e8fefc8 --- /dev/null +++ b/score-server/src/main/java/bio/overture/score/server/config/ProfileConfig.java @@ -0,0 +1,26 @@ +package bio.overture.score.server.config; + +import bio.overture.score.core.model.StorageProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.core.env.Environment; + +import java.util.*; + +@Configuration +@Profile("!test") +public class ProfileConfig { + + @Autowired + Environment environment; + + @Bean + String activeStorageProfile() { + HashSet activeStorageProfiles = new HashSet(Set.of(environment.getActiveProfiles())); + activeStorageProfiles.retainAll(StorageProfiles.keySet()); + return StorageProfiles.getProfileValue(activeStorageProfiles.stream().findFirst().get()); + } + +} diff --git a/score-server/src/main/java/bio/overture/score/server/controller/BaseController.java b/score-server/src/main/java/bio/overture/score/server/controller/BaseController.java new file mode 100644 index 00000000..370b9245 --- /dev/null +++ b/score-server/src/main/java/bio/overture/score/server/controller/BaseController.java @@ -0,0 +1,27 @@ +package bio.overture.score.server.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; + +@RestController +public class BaseController { + + @Autowired + ApplicationContext appCon; + + @RequestMapping(method = RequestMethod.GET, value = "/profile") + public String getProfile() { + return appCon.getBean("activeStorageProfile", String.class); + } + + + + + +} diff --git a/score-server/src/test/java/bio/overture/score/server/config/TestProfileConfig.java b/score-server/src/test/java/bio/overture/score/server/config/TestProfileConfig.java new file mode 100644 index 00000000..7d5697c6 --- /dev/null +++ b/score-server/src/test/java/bio/overture/score/server/config/TestProfileConfig.java @@ -0,0 +1,19 @@ +package bio.overture.score.server.config; + +import bio.overture.score.core.model.StorageProfiles; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +import java.util.HashSet; +import java.util.Set; + +@TestConfiguration +public class TestProfileConfig { + + @Bean + String activeStorageProfile() { + return StorageProfiles.AZURE.name(); + } +} From f81f34a85608e24603151369bd18e2902bb83191 Mon Sep 17 00:00:00 2001 From: Anders Richardsson <2107110+justincorrigible@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:26:01 -0500 Subject: [PATCH 18/18] release 5.10.0 - bug fix for issue #385 --- Jenkinsfile | 2 +- pom.xml | 2 +- score-client/pom.xml | 2 +- score-core/pom.xml | 2 +- score-fs/pom.xml | 2 +- score-server/pom.xml | 2 +- score-test/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 048dbe32..00d60863 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -154,7 +154,7 @@ pipeline { steps { container('docker') { withCredentials([usernamePassword( - credentialsId:'OvertureDockerHub', + credentialsId:'OvertureBioDockerHub', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME' )]) { diff --git a/pom.xml b/pom.xml index d66f44bb..7357819d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 pom ${project.artifactId} ${project.name} diff --git a/score-client/pom.xml b/score-client/pom.xml index 6ebba856..547ca585 100644 --- a/score-client/pom.xml +++ b/score-client/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 ../pom.xml diff --git a/score-core/pom.xml b/score-core/pom.xml index fe7e2fe2..5c9aa55f 100644 --- a/score-core/pom.xml +++ b/score-core/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 ../pom.xml diff --git a/score-fs/pom.xml b/score-fs/pom.xml index 1f02ceb4..358b7301 100644 --- a/score-fs/pom.xml +++ b/score-fs/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 ../pom.xml diff --git a/score-server/pom.xml b/score-server/pom.xml index aea560ad..f115e99e 100644 --- a/score-server/pom.xml +++ b/score-server/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 ../pom.xml diff --git a/score-test/pom.xml b/score-test/pom.xml index 84971215..5d7df4e1 100644 --- a/score-test/pom.xml +++ b/score-test/pom.xml @@ -21,7 +21,7 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S bio.overture score - 5.9.1-SNAPSHOT + 5.10.0 ../pom.xml