From 4343e1f1035baaa22f117d119c6e6bc35b1e385b Mon Sep 17 00:00:00 2001 From: Tom Clegg Date: Tue, 12 Dec 2017 18:56:07 -0500 Subject: [PATCH] 8311: Add git_tree mount type. Arvados-DCO-1.1-Signed-off-by: Tom Clegg --- build/run-tests.sh | 12 +- sdk/go/arvados/client.go | 1 + sdk/go/arvados/container.go | 1 + .../arvados/v1/schema_controller.rb | 1 + services/api/test/test.git.tar | Bin 256000 -> 122880 bytes services/crunch-run/crunchrun.go | 16 ++ services/crunch-run/git_mount.go | 75 ++++++++ services/crunch-run/git_mount_test.go | 164 ++++++++++++++++++ 8 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 services/crunch-run/git_mount.go create mode 100644 services/crunch-run/git_mount_test.go diff --git a/build/run-tests.sh b/build/run-tests.sh index 7d1d4c9e6b..45f603d4ab 100755 --- a/build/run-tests.sh +++ b/build/run-tests.sh @@ -323,6 +323,9 @@ start_api() { } start_nginx_proxy_services() { + if [[ -n "$ARVADOS_TEST_PROXY_SERVICES" ]]; then + return + fi echo 'Starting keepproxy, keep-web, ws, arv-git-httpd, and nginx ssl proxy...' cd "$WORKSPACE" \ && python sdk/python/tests/run_test_server.py start_keep_proxy \ @@ -821,6 +824,13 @@ install_apiserver() { ) || return 1 fi + cd "$WORKSPACE/services/api" \ + && rm -rf tmp/git \ + && mkdir -p tmp/git \ + && cd tmp/git \ + && tar xf ../../test/test.git.tar \ + || return 1 + cd "$WORKSPACE/services/api" \ && RAILS_ENV=test bundle exec rake db:drop \ && RAILS_ENV=test bundle exec rake db:setup \ @@ -904,7 +914,7 @@ if [ ! -z "$only" ] && [ "$only" == "services/api" ]; then exit_cleanly fi -start_api || { stop_services; fatal "start_api"; } +start_api && start_nginx_proxy_services || { stop_services; fatal "start_api"; } test_ruby_sdk() { cd "$WORKSPACE/sdk/ruby" \ diff --git a/sdk/go/arvados/client.go b/sdk/go/arvados/client.go index a38d95c2e6..24f3faac16 100644 --- a/sdk/go/arvados/client.go +++ b/sdk/go/arvados/client.go @@ -245,6 +245,7 @@ type DiscoveryDocument struct { BasePath string `json:"basePath"` DefaultCollectionReplication int `json:"defaultCollectionReplication"` BlobSignatureTTL int64 `json:"blobSignatureTtl"` + GitURL string `json:"gitUrl"` Schemas map[string]Schema `json:"schemas"` Resources map[string]Resource `json:"resources"` } diff --git a/sdk/go/arvados/container.go b/sdk/go/arvados/container.go index 7e588be17b..16726b76d2 100644 --- a/sdk/go/arvados/container.go +++ b/sdk/go/arvados/container.go @@ -32,6 +32,7 @@ type Mount struct { Content interface{} `json:"content"` ExcludeFromOutput bool `json:"exclude_from_output"` Capacity int64 `json:"capacity"` + Commit string `json:"commit"` // only if kind=="git_tree" } // RuntimeConstraints specify a container's compute resources (RAM, diff --git a/services/api/app/controllers/arvados/v1/schema_controller.rb b/services/api/app/controllers/arvados/v1/schema_controller.rb index a237829ec7..f413755838 100644 --- a/services/api/app/controllers/arvados/v1/schema_controller.rb +++ b/services/api/app/controllers/arvados/v1/schema_controller.rb @@ -60,6 +60,7 @@ class Arvados::V1::SchemaController < ApplicationController websocketUrl: Rails.application.config.websocket_address, workbenchUrl: Rails.application.config.workbench_address, keepWebServiceUrl: Rails.application.config.keep_web_service_url, + gitUrl: Rails.application.config.git_repo_https_base, parameters: { alt: { type: "string", diff --git a/services/api/test/test.git.tar b/services/api/test/test.git.tar index faa0d656d392c1862349c69234ae408ee8dbe738..93cff81893fec9d598908246ecabc045c1306db8 100644 GIT binary patch literal 122880 zcmeHQ2UrwW*B(GD2x2dZWo>{;nLfK}P-1V01&t-j?Cva}z~b(rSg-~wCPqo30gXX4 zD)t)DSWpxTc0W7zuF=?I{qHRB2NrN=hTRpDJI^x=Gjq%AdG9&5o%>z`r#JW@);&;g zFer-fS8$kKjn6Ow$4CN0F`NYNX+F4&vhHVPryiv@usWH{7Fm_VJPbVkN>*phGQa~Y z4u6IuNr=BK%FF-b?;RX!Ekht0e+(s13gT~j{5!VuYis#jdHm^uc0acsKvA4Q^4Wh3 zWe6ORp_c!Yf+_yT?Z1xGG?#%tdY=%ERqK7iS-pYNITe%>eDbf9Kz{qL=JYCEXrv)j z8)3m;Yfk?$3^UPxoFZwc{}zOx$fN=zBG_PEJZaq3Wm%n%Z)muW)7 zIGKB%QsFK$Xk~m1@Se*P$s1aXB1K%HU*y++V?|)`?-k$v1HC}l{5_iU@74{zoa(`k$b9{fF)UA_Qu|$4ZJ&YQRBq zxLl#a2o{rLtV%`VYD`IU6iUlUIjO)%Sif6P=p`trLiFFj2J0<494Nv5<0$C=!|`A1 z7nJ#~*LQd)tkqsUt zcqJ@yX%Tf~`nKbZV}5M$s6fW>L5Yw+e*IVK*a%e!XIb-a9Oo4^|AXNu1MR;}%13_u zRoVzmXt1R-Hf#S0($xNw47C52hM~~(2B@?;?rW!V|BU}>w7PKCFr3rr!6>lo3mNKE zjvodL*Qz;iXV67)PUV2D=WjG@m>%4PX@l9YFfeu$6{%)Hfyxb5Xom1%iIPBm{nsjo za4Lg^&A$Zuk1+%o|A*~=>lc;6@#i>8b^s;x{|GQ84Dq)<{78}b6Bx-7U|*|D#J!=Lx*9vgG;e_6ebg^w$Zye;k8p_tjh=p{@7h3kJLs~T## z8bE^mrztr9XOogrIQ~k?a_A!x+J88l|FsGFND=ivz+c$3kf5(LSO4Rv>HHrliA+hU@OJ0pbHlFI z8}#J%1Fx7Lnrt3rr~9j|okM?lQU@~O;?2>QSI2d_kXZw3+X@UU!{Z}Lpm6&i8lllz zt_F}&|1+Td5BvYtFBpa6PcfE5UsC;#LHwvCX!_ns&V`u$h!k!tlF zh+?G&BY#>F$glrkCdbl)|3Dn#>wgRfE`hNAw?R=V1b>S!0yAg-ags8z|Cn+8FSP&G zF919?LJpZwM^RY-2NsaY{KEByD8ndO%Sis#o6Wv$t%}lV`Ke{jTcr*6m0^T}0$4LB zF7x8YpUZ)#;b8HJM`%Q-A(Rbk(p(0nnxXHh^~ymZ`fu??Abj}}>HmXc(Es0hpyx@s zDEuwC2t+*oVEPx1|K~x;djEbHf6FWa;qm{_`tO4EKS^QG|I2!y=Si8zM#ur{|2#tb z7yX-G|1CT2n=2;1e2J_7!TL{F|L2O&s@FpB=b}|%QEJX|+4A^*$o>OoB9s0fPDA@| zIr)DmrG_%V`y&g}d+|QLdYPA(7A)-7@&Du$122tE8~%ln9mr@MavnQ1lywb_05J?9 ztU<66`+- z*MFM;Wu@Ey$N!(@TNcmBoc%{p)Ab*K1`y8wSR9AK5`@ERg-PYV^USFKqxi#1k46m} z=0(VHC0P0sEZ0R6G)-H=4?w*ACnz}nXPYu;7Jm!yLW;+q1O))j|JkAh2*ba4Q-Wse z{{sFWB*U-&h4X*bF9Be(Cm;W#5`$eN>r1`lH~$p0omX#b)p z!t}p*yl@iiKiCrrw*PHW%*5d@jTcA){tOPse{2Ci;_c(@)4HoRA{cn{4Yg8^#`+&@ z=)hmWVR}U|(Am#^mGd6MXy6hg>uRO%$(L;I{%<<1){yUo$&I=9Cc!_ITM7El8v!pC zqd80|CkR@hkjv!+tzuLvMxn+Tf|Dz8OoO8o$+4_AANo@f#((fTZGk_p)%=F8IXZ57 z#V8!l@BfWcH1Gcb=l`u=AOrl`bOE{W{Qu7LD?}$Qj@#vuhB_nf=QSuF(AfX@p2}aY zv1@kb+e$4v_xSm7(5U{H{gJJ6RxyEH8n!*`+-c8m1AbkK^&Wi6Z&~AxLFI1GI<;-- zo%I8LBB}(qbgo#Aov|RG!?CJ!f*wsBNOEn4?l_V;XyefJKZV{I`u@zdq5CF`js9_C zrZ#*=1-!faJqNd6>iexNQ)51nFu!h0y*C@N`e`Af6=j3x%9F-7cDvHHQeFR-|ZUwdE<@EpE;(5bva@Dv_qLZgI4P+ zEdq~@Pnf{I>=bvbLfC{llW()>YgUv=IX$y+^qZ_JGrg07t90>m?^tm~{j~!p&6z9j z^}O<=Zu%7q{up)B`@3I{tqEE>ae>A&Y*+o(?T5wfzcq1c&+!>4+hz{9_o``|)a{=4 z&g>mf@0S+8y}34TbJn2aedqn|pkYy^^a@)_t?KyrliGfNFM6l z?#WE`62;yPHQINL^NrRVXqt5PuQj9ZMfNyR;a2LoHB9XVpS!>NtI?v(KRpk04}DhF zx9a0sRUFT-Z4H#Z5N$LdJJQ6(j&OXD%CQWq5Qd?-d zZ@9HTenG2K$@WOfL+2MJA>}XK+y{sB-PO3&gE(YSLWjU5XWqVaMplk?aW)BA_Ux=j ze{#!r??@=`RJYz{bbe3t;l;0!ol7fRG6@;5Qt@-r`eA+?1vGCHwK)6R#w96s9Z;1TAgJyPelQgtZsF#FDNjNQbXJHU?OILdAUX?%Cf9&tEk z*ZtRs&nMCIrcMeQvv0n;?~MA79sQSEUuP|ugVpVSs5;t={m1#WLHYLo1@@l-?SE+h zEs1pDX}vdeSAjRY{r}Km2VPp^-g&V&XL%6c-02L${Ois#qmx$pCUu@Y>-%Ll5BDB8r&hwZee2xr9P8h# ztxI}~r#`VAS10d^S%k|54;{H6W?}O8ey-iVW``Vc&{HZea2YJ5m zpLU>s#FQq#Ki|9Sewem$YUFYMW+4Ii+4M&7zAv8~sCT~oy%&$uvku2Uu6>_~z3Q{+ zA{qM=w_{ykHTLd4-1BAn&PM(H9}U?ud{kD44z=4wc#LxnR6nU3xGrIHoPU`WzV^)l z=8Lm&xBnk7Qy4IZ=fT+;{NFI!Y}tPWOxX(Xe>HHOSXj%TPtY_~?==5rOEkZ@pP4?^ zxB59ZKal1}J;c@j(${~x@h^SA#n zhJpJ(iIK4MumNC6wbt|IW~?Z2cCF{l4HW#a#V(O?7!>c1pmi;RS+IXTJ7fv*;>BuP}Q zqQJ&)B(4EZ1xbK6;9DprC#rGLA@~Dn zDMSJ*Ft`Z)m&^-l)c=BhpSgZuXhHr@Ks*KgzXT#!ykL<3vv~6R)ME?N|Kjn2N@)L) zkpJH{B}*9o{2URd_LA5FG}rzkaMS%?X%b8c!v3EPia^8c`9B_6BY$&qStQ4WacY?+ zDlBZISI&)-&}O1cS~D?kG?C53?5MDrD6y;v(|?`LOU0@}IB9I4M*B}ux$QmEEC1SL z{vRy=0sTMN|Cb1=h-hZ<|A*E=M5_6N8twlF+W%kymqV4h*r8Yi~q;se+Kp+*8f%lJx{X2 z@R#iRW6a5H{SP*K$hZCnqxdEv?EmG#$y)z{{#ri%=bYY`wX%chmM{qj)Blga{|x4T z;rze#3k&3bw!Vx@at^}u-#Dr#`Dci4{{#PT*#4I+Z!r-?;4j7X)A%Xk@dy0RkpEW< zjFQ8Oz~83)&wvsb_WvZKDmfj2y!&BQmF2*Ors1}rfF#WeZ|1(_wVL^~T zkd!d|KLYNxq67V+?hF~h3P_m4I;us}?<0_UyS&r4HIaW?9IhvwX7^xyjmA54RKN`>o!|{I` zz>f&z|Fia|6qj2tmqYNsb~WWo%)K||Otds7qAAy*rSHx0CgySo3grd-P&iY*Ky&UCOl}K zo&CP&3uoT0_L$)O2H|e4_4+B3;zE;Zx=(61`Oudeg5QU!nzR^kWf?k0!#FN!vEh_s z==cs-%4JizAO%++nZn{vO?#Du@1zNr$BFz!tX{@bw4 zbtkNBee_DT)Vl*aj`Q%Tb7AW@{ZF*Y*iO73su=BET6?!rtA;h*l$`qJ>$JE2$JOtT zv`87B=5%($+kunPdaXS_{n;!3_N|+2?{^rB{;U!?d;82(pOY=#SKT<)=d-FWdR;kq zSvGl5r-J{NgKH`{hl8^{c>bhz!_<+3M&q7~o$kK9J9#@7R&`I;+0+*sx2!%=XXO_W zolnkam=&a3^}^bQ)m-{;{|CK+)yZUtx&0l?y*DT568hfi?LWS?SVDh0{4B&A|C8Lu z=>M79|2Ovk#I^rHXukjVq5U5Su-HG}{0~m!H1z+mN%73P|3jiH*f8K*Kc_UbV!IcL z^ntBAxy`v#s_mX;PfP75*Ln|Wy!Z9_t9$?0`r_rImw)_V|5X|Fm7dFH1y|FJb*jBh zkKJoje+awb?9ahNZX9DD;Ztken0vHbL|4DBen6|ZZd|u+-|h9C9{R3!S+(+Mg=@Np zMB-!bSLbd#-o0<*#lx4&HmovWTI3q_%41Py|2OE}^tr=EAFIFl>Csx-JGFjdS0}4m z=sm~rb)yqs?|wP6$L3@YDsY!)`k|f2kMBIX)8lN*OwVIG8#F$Zc9hJ_ICJLE$vsEO zQ)e)Um*b3Oe|@7%L<{EUOkJTMCN-B2x^u}v1#D}`a-iz-~lzaSmi>us4Kjq-#N41`ZSBqJtdvhhc-U|m=WA9}* zm!-M&jPrZ_cv-}_ZfSpywsY1#b8k5di%z@-x-R9B^2_YOz6ls&AA3FN__phDFRxxt zIy7;%vh?3&jz39?b7=WuWBdL$ylzBa^3`7qM4Dg~gO>0yz)lMc73k5)%e#rc_W@52 z_V%I6*EA1btS1O*)^ctu7+0{{73h5V7Wmw_ga3=UotMlvn zf9Li7hlPKv`=)=-AqUo9LZ0ugV5b0|+%r4(%l3#%y8XeTGTm6AM&0Ruj;eO8$Le2w zMhB1Ra*}&p1@T=_sb%4L-mboC?pICTHkOIe}?wIq~R}l5tv!~Uts+w;D3hmKP3%+$%_CawEw^kU~vA|76m|r{m(<~BJRt? z;}7_s;rzciAxjJ`4S$A^Gjc+%q7^KT$#L*MNy%xIiUcH*G^5ebDw@C*gfjc1MB9Iy zByh<8BoR?@(Tan=(455MkD~ng54iqQsD!15lZLv4gRj(rO=i7ghzQvsVCvYPF{2xZ+kpDxHs6|I&7!DA36R3iq!J=D~VrfFD zB-Ip3(F!?W;o~q=q2|=;yhPsFtv@F~;jJPSa$KR*U<@TEF@i!BO3?aKvA`viWf)A! zV4NH)7}b2k(Mf0vGjHOMyF@hn0_XpY_TRSr-*Eg#JeU$lwDLi-m*5mx_y1paT> z{t{v&Z>GThFC@?Z0sH^fF9HJjzlAmv^AdTBY$g_rYQbh=-o#-uF;B4) zrvJ9*|E9qHFOdH;4^US6*DU@fv>sAEL;Uy;P4V-;5PvDs78ge>{(SfxS{K0?naAH` z{|_9cq5rpF@fIr}Bz-TI_&)i_X7ryDzuLc`NX+ZMDgPH3Nre7i1qEq^CuZ^gSp4sh z|IZ3&7fezZ{*qn)j2Rl|f53zee+7r>6-5j1zmp6D`Tq)nWrZhTQV;UKTS2a$N|M6# z|0D3f!~I`vQiLG?yG_JgVlxq@|B_w5jlY|(^qGS7er`L!*e1xg{u=}SKd}98lQJU$ zf7|lE!|}h8hQCeu-$~H^hvUE2F9O2!-^%>&z}efx{sTS(IR9&X^bsU4|9h`r97Zt7 zNjtzb(&K_Y2tnQ;hz|MPg#UfuzWzTazl%w8ukN^Xwqs@&nW4d-6A%ZmMl|PxYaLJD z)MQ5QE#r|Tm)tx@CXcsE3bVy;fq96RfH3{HJ^woa?Z0?1CBzVh|3~0|hxT6rn&P8C z{&(>*`!~f9rvJJ8Z_<9b`2IhQqR{_Gny^L25{EzU2P%F>SOWeG2FHIyA}K96+^R8jn&DzMC-1YX(+2JCuy3)6s$^x z5gg4Dj2go=xHoSyq!mpV%LWpVVE=hUy~N2t&I}Gw+1E54!iT>l>5u^Y;r|ELsshH z)QT}$k9k?ck2S9G;PxVn4EVA}`>svzC*nAj`n8Z*`}ouoc9|`@yY%+lRxa*R-=$8gs|5Xhw(r$c$6Z^z)&|y7xAT3o z%`rOBWv`#pcv(fqqksJNvhfC&=B(Y=-IwHotxkIE}&A`-93`WI9=h&teU;tW8DI5xWl=q!D}-2c0G7ux$DoW zx)oOgHq;#Y)QtVzgXMLpq5F57Yjan*qM6&;1<(3;^cZ!zERr&({KLKD+735-l^A{J z8_kuU4^_FjD5mnKzm1{Q^c92XzohK{VuN1_v-poopg4OB zeQNs(g6GKww3_3+On>j<95P1DT#_G(%=6RkBp11i#vlWfU^_zCde#>9p zSC*~$-~ZTONIK^lvg@Fmj4&_|7=o(ApfsT#9U%C5vKnif&Uk_|7=obgyGLm`B;zt z7XzDp2 zB4*y08~?$8vqygWPvRJy|2HF5%e-z_U*@9>jquTjI5{s*hw1 zs*u5aL6I4>vS2QP)3F9l1`38u8)b-$GB|On5UtGD4VN|O+P#CUTf1Jp{5rI20I6jy z1CdozF{A&C1?WGGJWmW5(C6&{I83j`XD0ejpm6=aRdLTvToC?}Xa2Ku;Q{`j|5qXW zp9CEL$%V+OS1_m#`9G~H;gX%WApI{M{io61e@Oo^%!L0R1N%R~_Mc4(4&?u|iI_`l zCW7=|vgcR!&*tlYaqT|}=k*`*|5?A-2*+QF=a*FcX@YP6LHtV+{yHvP3rdT4`WFfP zKbqm!|3mysBK}%kXfPNs67gxG?LUsa0%KYM)8OBWU4Wzcb) z7oSiOAHn1Qq4qxtHv7vr{)3Yk4(I=hkfvoHYt#fqU>XuvC@6v?H3Y39P$i?#P?QE| zloX0<2sL;C2Xiee_mYyDWc?R0CMaJ2QON&cqXGi;-$sHiq1i~*|2*}7gch^`LL-Z8 z0*KdtlH%8YLH;l67aD?<;|fYat0)E~DGd$wX;En~TCI^|w33u#EU95t3ONSrf9qrM zF>;Ws|00%viPwMN5eW6)CdC2P|27eGiOoc~{!8BeN6Ppg7y*LgKei||g77ci_8(I4 zM;VB}E#Nn|{yW?Mt9aXgn4kX#%ARlh52K*}zfI6bkYersVbDc!uw!5&q^y&TAp2ju z?LQ>ge~KZX|G#wrH%V0#{`@j9F%y3|dGY-}asD4*;{oXZVS zV!?nB$FMAct5}?6<*Xb`9Z{qLWt19?8dEEc+duI5e}MlVEdQYL*Z(+8(2)PZI)Iy` znuq`2DX~Iy;{0!U{{O0uFBI*(7hY%n?&j2BV&6yht?qR3+R*;^nI{8QUmg-vefI{Z z5M|xOfO_21FB+9idNC56o%GBv`ZhMX=892W(o;g)AFAv!;_IN#*8dvU_M1JPZ$s9V z&+0I|PW+g2>wCZTNZIZ)*DWUW&c5^CHfPSdZ995%!~956ZSp$L`!$|BY-+rC zf?JbsH$Bw8j$Ke%6BITTIlVWYe6l6BYAl8B+v#;m-eYh7Y1xlb5=d zGwwxzA@;HHhZ?k*yzkhk^a)GW*X=$sb=>O-fmfSX-umZjJ7o1O7yG;c8b;s$oo=SWgu`P5Zl`viV-0|M*O@!+9OfgVRZ_XlKTcJCC3OvARl zN^H3G=9`#B0hO3}GiJPdSZP6>*~*Zhpok&Uf35AYH}d*|2XW)qA95)(rf&84)hE_& zt-9sc(nyoD4OfxTiK-yAvNVEJK+0?eJ1F$(bF%w^LnnL=U+%oJW4AsXyB*Hx`{>0@ zd!*;`(sz>hulVrKs`XjTx%1|FBy%^Dn_j!Xh=d)t{q?PHfi6%exc!aX0Ld$`>4l+V{yg@O9qty)};F zaPH^E6~nzRgzvr-_@O1~bOhf6&ypttP`e@4ILm-^&7EaIn4->d;GLyTe)Pt8R_oWf zdg|$jrK>iNo3&zn^x_{M%$Vf%eXQ>OFj1qpa#~ zvmsxMoV{jE`{omW_%S`Q-SbH2zrtTu-!LKh)&2>CcBD8qh^_Oe-u+7V1D70qI%RZk z?>$*x%nitN7{9aYmBFdddIpldw7~j$Fb6tG2IwEb0BWDha*SZz=3)lOM?L^zQN_pAB~3 zX#eCyTkScfMXih>)aw>)$JFfEd0p+g=}{ZnXnUO)t43l5#J3C#-rbdPLau^+DrN$+ zw*y?WfDD|$nF8+HfKv^gZ30&sTzeGOoN(~meNUzCubuHxlqd1{i{Adh?D#(l$bRyV|1-w@U!nhx^@~8x{tu$YbDZFqzx9E! zQ4WIiU!vX5{R!gjKUn_<*MH@T&#G79_)Dh$HEaKI++_S0qcI%r|7ca*a}yWp|CyKn zw+Po?C!xM%MWprr%ZOn0l8cV@ufp|TGX1Yv{U>OX@jr~FG3ftkeegjJkpI^vVlJ_n z2-5%J(f=CtU)=mZMZ)#}wka}#@GlO6af14Blf&9Nhn~8b(e~a5p zEFvw~OtfUd5TyUbqyLp+|G@wt^#8Xc&M++~0Vn||0Vn||0Vn||0Vn||0Vn||0Vn|| z0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn||0Vn|| L0VsighXno)bj9R6 literal 256000 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 D&hbD# diff --git a/services/crunch-run/crunchrun.go b/services/crunch-run/crunchrun.go index f3f754b59d..d262b3d122 100644 --- a/services/crunch-run/crunchrun.go +++ b/services/crunch-run/crunchrun.go @@ -538,6 +538,22 @@ func (runner *ContainerRunner) SetupMounts() (err error) { return fmt.Errorf("writing temp file: %v", err) } runner.Binds = append(runner.Binds, fmt.Sprintf("%s:%s:ro", tmpfn, bind)) + + case mnt.Kind == "git_tree": + tmpdir, err := runner.MkTempDir("", "") + if err != nil { + return fmt.Errorf("creating temp dir: %v", err) + } + runner.CleanupTempDir = append(runner.CleanupTempDir, tmpdir) + err = gitMount(mnt).extractTree(runner.ArvClient, tmpdir) + if err != nil { + return err + } + bind := tmpdir + ":" + bind + if !mnt.Writable { + bind = bind + ":ro" + } + runner.Binds = append(runner.Binds, bind) } } diff --git a/services/crunch-run/git_mount.go b/services/crunch-run/git_mount.go new file mode 100644 index 0000000000..a792741ae4 --- /dev/null +++ b/services/crunch-run/git_mount.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + "net/url" + + "git.curoverse.com/arvados.git/sdk/go/arvados" + "git.curoverse.com/arvados.git/sdk/go/arvadostest" + "gopkg.in/src-d/go-billy.v3/osfs" + git "gopkg.in/src-d/go-git.v4" + git_config "gopkg.in/src-d/go-git.v4/config" + git_plumbing "gopkg.in/src-d/go-git.v4/plumbing" + git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http" + "gopkg.in/src-d/go-git.v4/storage/memory" +) + +type gitMount arvados.Mount + +func (gm gitMount) validate() error { + if gm.Path != "/" { + return fmt.Errorf("cannot mount git_tree path %q -- only \"/\" is supported", gm.Path) + } + return nil +} + +// ExtractTree extracts the specified tree into dir, which is an +// existing empty local directory. +func (gm gitMount) extractTree(ac IArvadosClient, dir string) error { + err := gm.validate() + if err != nil { + return err + } + baseURL, err := ac.Discovery("gitUrl") + if err != nil { + return fmt.Errorf("discover gitUrl from API: %s", err) + } + u, err := url.Parse(baseURL.(string)) + if err != nil { + return fmt.Errorf("parse gitUrl %q: %s", baseURL, err) + } + u, err = u.Parse("/" + gm.UUID + ".git") + if err != nil { + return fmt.Errorf("build git url from %q, %q: %s", baseURL, gm.UUID, err) + } + store := memory.NewStorage() + repo, err := git.Init(store, osfs.New(dir)) + if err != nil { + return fmt.Errorf("init repo: %s", err) + } + _, err = repo.CreateRemote(&git_config.RemoteConfig{ + Name: "origin", + URLs: []string{u.String()}, + }) + if err != nil { + return fmt.Errorf("create remote %q: %s", u.String(), err) + } + err = repo.Fetch(&git.FetchOptions{ + RemoteName: "origin", + Auth: git_http.NewBasicAuth("none", arvadostest.ActiveToken), + }) + if err != nil { + return fmt.Errorf("git fetch %q: %s", u.String(), err) + } + wt, err := repo.Worktree() + if err != nil { + return fmt.Errorf("worktree failed: %s", err) + } + err = wt.Checkout(&git.CheckoutOptions{ + Hash: git_plumbing.NewHash(gm.Commit), + }) + if err != nil { + return fmt.Errorf("checkout failed: %s", err) + } + return nil +} diff --git a/services/crunch-run/git_mount_test.go b/services/crunch-run/git_mount_test.go new file mode 100644 index 0000000000..4c6ce7f075 --- /dev/null +++ b/services/crunch-run/git_mount_test.go @@ -0,0 +1,164 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +package main + +import ( + "io/ioutil" + "os" + "path/filepath" + + "git.curoverse.com/arvados.git/sdk/go/arvados" + "git.curoverse.com/arvados.git/sdk/go/arvadostest" + check "gopkg.in/check.v1" + git_client "gopkg.in/src-d/go-git.v4/plumbing/transport/client" + git_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http" +) + +type GitMountSuite struct { + tmpdir string +} + +var _ = check.Suite(&GitMountSuite{}) + +func (s *GitMountSuite) SetUpSuite(c *check.C) { + git_client.InstallProtocol("https", git_http.NewClient(arvados.InsecureHTTPClient)) +} + +func (s *GitMountSuite) SetUpTest(c *check.C) { + port, err := ioutil.ReadFile("../../tmp/arv-git-httpd-ssl.port") + c.Assert(err, check.IsNil) + discoveryMap["gitUrl"] = "https://localhost:" + string(port) + + s.tmpdir, err = ioutil.TempDir("", "") + c.Assert(err, check.IsNil) +} + +func (s *GitMountSuite) TearDownTest(c *check.C) { + err := os.RemoveAll(s.tmpdir) + c.Check(err, check.IsNil) +} + +// Commit fd3531f is crunch-run-tree-test +func (s *GitMountSuite) TestextractTree(c *check.C) { + gm := gitMount{ + Path: "/", + UUID: arvadostest.Repository2UUID, + Commit: "fd3531f42995344f36c30b79f55f27b502f3d344", + } + err := gm.extractTree(&ArvTestClient{}, s.tmpdir) + c.Check(err, check.IsNil) + + fnm := filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0644") + data, err := ioutil.ReadFile(fnm) + c.Check(err, check.IsNil) + c.Check(data, check.DeepEquals, []byte{0, 1, 2, 3}) + fi, err := os.Stat(fnm) + c.Check(err, check.IsNil) + if err == nil { + c.Check(fi.Mode(), check.Equals, os.FileMode(0644)) + } + + fnm = filepath.Join(s.tmpdir, "dir1/dir2/file with mode 0755") + data, err = ioutil.ReadFile(fnm) + c.Check(err, check.IsNil) + c.Check(string(data), check.DeepEquals, "#!/bin/sh\nexec echo OK\n") + fi, err = os.Stat(fnm) + c.Check(err, check.IsNil) + if err == nil { + c.Check(fi.Mode(), check.Equals, os.FileMode(0755)) + } + + // Ensure there's no extra stuff like a ".git" dir + s.checkTmpdirContents(c, []string{"dir1"}) +} + +// Commit 5ebfab0 is not the tip of any branch or tag, but is +// reachable in branch "crunch-run-non-tip-test". +func (s *GitMountSuite) TestExtractNonTipCommit(c *check.C) { + gm := gitMount{ + Path: "/", + UUID: arvadostest.Repository2UUID, + Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", + } + err := gm.extractTree(&ArvTestClient{}, s.tmpdir) + c.Check(err, check.IsNil) + + fnm := filepath.Join(s.tmpdir, "file only on testbranch") + data, err := ioutil.ReadFile(fnm) + c.Check(err, check.IsNil) + c.Check(string(data), check.DeepEquals, "testfile\n") +} + +func (s *GitMountSuite) TestNonexistentRepository(c *check.C) { + gm := gitMount{ + Path: "/", + UUID: "zzzzz-s0uqq-nonexistentrepo", + Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", + } + err := gm.extractTree(&ArvTestClient{}, s.tmpdir) + c.Check(err, check.NotNil) + c.Check(err, check.ErrorMatches, ".*repository not found.*") + + s.checkTmpdirContents(c, []string{}) +} + +func (s *GitMountSuite) TestNonexistentCommit(c *check.C) { + gm := gitMount{ + Path: "/", + UUID: arvadostest.Repository2UUID, + Commit: "bb66b6bb6b6bbb6b6b6b66b6b6b6b6b6b6b6b66b", + } + err := gm.extractTree(&ArvTestClient{}, s.tmpdir) + c.Check(err, check.NotNil) + c.Check(err, check.ErrorMatches, ".*object not found.*") + + s.checkTmpdirContents(c, []string{}) +} + +func (s *GitMountSuite) TestInvalid(c *check.C) { + for _, trial := range []struct { + gm gitMount + matcher string + }{ + { + gm: gitMount{ + Path: "/", + UUID: arvadostest.Repository2UUID, + Commit: "abc123", + }, + matcher: ".*sha1.*", + }, + { + gm: gitMount{ + Path: "/dir1/", + UUID: arvadostest.Repository2UUID, + Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", + }, + matcher: ".*path.*", + }, + { + gm: gitMount{ + Path: "/", + Commit: "5ebfab0522851df01fec11ec55a6d0f4877b542e", + }, + matcher: ".*UUID.*", + }, + } { + err := trial.gm.extractTree(&ArvTestClient{}, s.tmpdir) + c.Check(err, check.NotNil) + s.checkTmpdirContents(c, []string{}) + + err := trial.gm.validate() + c.Check(err, check.ErrorMatches, trial.matcher) + } +} + +func (s *GitMountSuite) checkTmpdirContents(c *check.C, expect []string) { + f, err := os.Open(s.tmpdir) + c.Check(err, check.IsNil) + names, err := f.Readdirnames(-1) + c.Check(err, check.IsNil) + c.Check(names, check.DeepEquals, expect) +} -- 2.39.5