From 564e6707a2a5c3a8251495c91be4632ed39eb703 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Wed, 30 Mar 2022 20:47:55 +0000 Subject: [PATCH 01/14] test: use valid squashfs/ext3 inputs Use valid squashfs/ext3 inputs when generating test images. Update test corpus. Update golden files to correspond to test corpus. Signed-off-by: Edita Kizinevic --- .../testdata/TestApp_Dump/Three.golden | 16 ++++++++-------- .../siftool/testdata/TestApp_Dump/Two.golden | Bin 4 -> 4096 bytes .../testdata/TestApp_Header/OneGroup.golden | 2 +- .../testdata/TestApp_Header/TwoGroups.golden | 2 +- .../TestApp_Header/TwoGroupsSigned.golden | 2 +- .../TestApp_Info/DataPartitionEXT3.golden | 2 +- .../TestApp_Info/DataPartitionSquashFS.golden | 2 +- .../TestApp_Info/DataSignature.golden | 2 +- .../testdata/TestApp_List/OneGroup.golden | 2 +- .../TestApp_List/OneGroupSigned.golden | 2 +- .../testdata/TestApp_List/TwoGroups.golden | 4 ++-- .../TestApp_List/TwoGroupsSigned.golden | 8 ++++---- .../TestGetImageMetadata/Object2.golden | 2 +- .../testdata/TestGetImageMetadata/SHA1.golden | 2 +- .../TestGetImageMetadata/SHA224.golden | 2 +- .../TestGetImageMetadata/SHA256.golden | 2 +- .../TestGetImageMetadata/SHA384.golden | 2 +- .../TestGetImageMetadata/SHA512.golden | 2 +- .../Group1.golden | Bin 33692 -> 33692 bytes .../Group2.golden | Bin 33545 -> 33545 bytes .../Object2.golden | Bin 33545 -> 33545 bytes .../SignatureConfigSHA256.golden | Bin 33692 -> 33692 bytes .../SignatureConfigSHA384.golden | Bin 33692 -> 33692 bytes .../SignatureConfigSHA512.golden | Bin 33692 -> 33692 bytes .../TestSigner_Sign/EncryptedKey.golden | Bin 36868 -> 40960 bytes .../TestSigner_Sign/NoKeyMaterial.golden | Bin 36868 -> 40960 bytes .../testdata/TestSigner_Sign/OneGroup.golden | Bin 42014 -> 42014 bytes .../OptSignDeterministic.golden | Bin 42014 -> 42014 bytes .../TestSigner_Sign/OptSignGroup1.golden | Bin 46110 -> 304158 bytes .../TestSigner_Sign/OptSignGroup2.golden | Bin 45911 -> 303959 bytes .../TestSigner_Sign/OptSignObject1.golden | Bin 45911 -> 303959 bytes .../TestSigner_Sign/OptSignObject2.golden | Bin 45911 -> 303959 bytes .../TestSigner_Sign/OptSignObject3.golden | Bin 45911 -> 303959 bytes .../TestSigner_Sign/OptSignObjects.golden | Bin 50007 -> 308055 bytes .../testdata/TestSigner_Sign/TwoGroups.golden | Bin 50007 -> 308055 bytes .../Test_command_getDump/Three/out.golden | 16 ++++++++-------- .../Test_command_getDump/Two/out.golden | Bin 4 -> 4096 bytes .../OneGroup/out.golden | 2 +- .../TwoGroups/out.golden | 2 +- .../TwoGroupsSigned/out.golden | 2 +- .../Test_command_getInfo/Two/out.golden | 2 +- .../Test_command_getList/OneGroup/out.golden | 2 +- .../OneGroupSigned/out.golden | 2 +- .../Test_command_getList/TwoGroups/out.golden | 4 ++-- .../TwoGroupsSigned/out.golden | 8 ++++---- test/gen_sifs.go | 18 +++++++++++++----- test/images/one-group-signed.sif | Bin 42014 -> 42014 bytes test/images/one-group.sif | Bin 36868 -> 40960 bytes test/images/two-groups-signed.sif | Bin 50007 -> 308055 bytes test/images/two-groups.sif | Bin 40964 -> 303104 bytes test/input/root.ext3 | Bin 0 -> 262144 bytes test/input/root.squashfs | Bin 0 -> 4096 bytes 52 files changed, 61 insertions(+), 53 deletions(-) create mode 100644 test/input/root.ext3 create mode 100644 test/input/root.squashfs diff --git a/internal/app/siftool/testdata/TestApp_Dump/Three.golden b/internal/app/siftool/testdata/TestApp_Dump/Three.golden index 6d1002b2..4e354d95 100644 --- a/internal/app/siftool/testdata/TestApp_Dump/Three.golden +++ b/internal/app/siftool/testdata/TestApp_Dump/Three.golden @@ -1,15 +1,15 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 -{"version":1,"header":{"digest":"sha256:635fa0a14a8ef0c0351ed3e985799ed1d4f75ce973dea3cc76c99710795cc3f1"},"objects":[{"relativeId":0,"descriptorDigest":"sha256:3634ad01db0dd5482ecf685267b53d6201690438ca27c3d7ea91c971a1f41f92","objectDigest":"sha256:004dfc8da678c309de28b5386a1e9efd57f536b150c40d29b31506aa0fb17ec2"},{"relativeId":1,"descriptorDigest":"sha256:db74cb63348414def73535c9f0f83e8ad7df61229ed2806f4da8b69d6d7464d6","objectDigest":"sha256:5f78c33274e43fa9de5659265c1d917e25c03722dcb0b8d27db8d5feaa813953"}]} +{"version":1,"header":{"digest":"sha256:635fa0a14a8ef0c0351ed3e985799ed1d4f75ce973dea3cc76c99710795cc3f1"},"objects":[{"relativeId":0,"descriptorDigest":"sha256:3634ad01db0dd5482ecf685267b53d6201690438ca27c3d7ea91c971a1f41f92","objectDigest":"sha256:004dfc8da678c309de28b5386a1e9efd57f536b150c40d29b31506aa0fb17ec2"},{"relativeId":1,"descriptorDigest":"sha256:04b5f87c9692a54f80d10fb6af00c779763aeca29d610348854bd97cd8bf66fd","objectDigest":"sha256:9f9c4e5e131934969b4ac8f495691c70b8c6c8e3f489c2c9ab5f1af82bce0604"}]} -----BEGIN PGP SIGNATURE----- wsBzBAEBCAAnBQJe+oD0CZCiDCfuf/e6hBYhBBIEXIwLEATQWN5L7aIMJ+5/97qE -AADY9ggAlW/Y+BssNOLcCAiu0dzZCf5BfbzmOUQ+VNajAsZyOIJnW1t19lDYoRNx -x3YolyyRfEmw9Kf1n6fctDHGPyzRIIOc1/0CVQzNzfKZQO+x0+9qvurILADijY/3 -1DKqhbxoO2a5iASXYHH9yYs3J82N3EKEYyFdDMTcHs4UijUnHvwcTt0smY6JQ9Su -vssWg+3qltuVjiYOQPgg9XR5i8suXE76poit9Ftp7jOD9eYtVcUEKRZLrVCsDJu9 -77QvejJmgquueYX4pM2EuH9EOFnDV3gl4Cuocsn5OLDgfhYuT1t5Hay1iAPpJqm6 -/EXQY7CECByIj6TCFurfXwc+uYSD9Q== -=rZoe +AAC46gf/VXyzZ649nttrX13JkM5kRVPlAIblBQxfoUxA1xwIXdRoM5ceDY0Em+YD +8b6Xl1w2sDTqo0R15cJSh8sf0ClFOvYpDQRNCwKx17k1Wd0gHcW4QVu6gJnlbNvN +o/EJdEN2TkbCM2aFvj34DAIfErRBIEsCeDDvJ/6WUSySWbnydfNU2pCsnK4A7l2H +KOXFzSaPijG9L/pU3O3vNZ+fXPffqHL9JVhs5Mt/Yo3oeoEnoVaKvJLGx/fyl+Gj +7qsfWFyHWzRCww9VFg/TCBeUku0CYRfXhxOgo4OuHNr8oo82rKDZU6+l3UZ2Sw8T ++kLe/zUkaILocGOvhvKdi630OGGb/Q== +=3Jq2 -----END PGP SIGNATURE----- \ No newline at end of file diff --git a/internal/app/siftool/testdata/TestApp_Dump/Two.golden b/internal/app/siftool/testdata/TestApp_Dump/Two.golden index 7d174b13ea69e384bbc26af0ff1119aafc9abfb7..cf6539a5affe42a355106ae187cae3eeafed6efc 100644 GIT binary patch literal 4096 zcmc~OE-YqZU|?94?wrKHz{J1^WHT}dG8_PsEI_sb5QD%^2*vObO8OM zjxdI#GzB(>lX0wa(jbKi4GeA?XOA2>IAP+f$&=TI2L&=Q2u)^QC(w`pwL%!=Vj$QF zF(vKEY$*8Iq_wU>8!;bpWIB?MeAyt!gm@$&|vUw$O-t2-rrTo|= zCfz7eQEfY3Cj&Dq!VV`zNO`twz}|2e4cYvf~ zzxSpQRig@0a5?k`O%@R9INFt?^5VFimu!<+8po%VOzhex)heUJ?=NBp(8^0E xG)Td|4p!&$vrBwI*Kj&}6B!%Cp*eMB<`VDX1|$ry5*YKjFqgNG-T(gk{U6=`mNozY delta 466 zcmWN_J948i007XLlw2Uq9w0L*&<9DVZ~E67r&xfzihi~Whl%|4ZlmafY1PVe4(Fg)eAU)M$%!S5z%JhWX+uP&QkAxn_oTG@) zh;Sxo!XhYQ4u6{Ih(SzQ7T>>bhmR%c1-Gw#>jots!<}#KJJ=4*)v=b7trfP@Ro}3F z&pcA~c5ON^QS+(e;FOdn#pEcqjVho8m9=(ICF`Q0nuVE)>3;Ehg<1%@vYBlRh)iBX zSsW&kypHvi(}(zcQ9h21QC1=7kZ^;!ZD$=og;Dr*-eFR;r0ho{Wpr`3=>GTLum3a4l#2iW diff --git a/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/Group2.golden b/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/Group2.golden index 7f89006ad95b15cb4b27d3632f5c1e3b9cc99030..13cc3e52cc40b8155e719b85c86f272f7a79afa9 100644 GIT binary patch delta 467 zcmWN}J93*q007V#ms}uC(tAdQ(0-v%VJr(20V~8$p<5OfNr;dBpvF!L&$!k_Qsp?g zLGBQ@uXrEt4Kv~BaffkOQlCY*dA3~@e=YKiQG|C9S*^>Rr=m3biOc?;A#+>*6GRcTxLS z_e5G~ud2QrPF)tICZmc~x{-R!)V-)D4TzUE3!7nNu4{YYM8$Zlj6Lgw@Be;%{SQwL Bm~Q|8 delta 467 zcmV~$y^@+h007{bD|vx5Nq;jIEbK0@g@xdOM*if)AG%#&QBagsL~QOZ#m!vpi=@iq zy%@Irw9;@YDCo-1svvxVTGg_M+_>Dzwh6kG1EB8 zpkd^Y@m%E`qMQ=|HOwG}I>;!6DN51f$4ButcFqNtnMt+^KE~6N)6XogOl`g+kT%#N zKd%!yv5%o_o){x3A18?)Y?3b3ZVHjm+9V(@19yK_vyE_9*$&F4w|A^{|B_5g*zZ2-La^)=KY1+{<5I!VOjndw;0L(SlqT*!D#gkbK@- zR&veh;82T}hP%ONf2!ifk@U-bZq`e`fhjz?NmI{sH`kN%VoJK`a_g+sy;F^l2``Pf z=r;+PnK7!pHQrXQlpx7PMP;wH)AK^}PZO(hP}!u1FdL`>--_W-8cq*Ac>MeI{XYPH Bmtz0` diff --git a/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/Object2.golden b/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/Object2.golden index a891e0f2b329dd64327eabf594414d19ccdb20af..5a050a1d66faac2a84dcca93638b30b4a1f2418c 100644 GIT binary patch delta 467 zcmWN{J93*q007V#ms}uC(tC!2&%!PgDv%IHSYQxX2zSda3y6<|5lE=9lfpBub&*s# zPHvDp#O<5+`EmF8argVr`@M)Dg&BbvkTH}2q8iXrEQ>^wRRRgd3PGBxD7U}w-|iVz zWr!I~X@(KezOqCB0Fsi5nfRp)t0_i0yZ!i?zb(+=%y^%*+K9W;uD~$M!*EoPTQrdp z2TS41hl4(~neQt}|4Q7G1F>!kIWCI}cdd`oL^N#h&VZr9vBe_;}eZ zlZt=!L1RXI+~_6gLbM*sUB<)JA%5dR8*Ix+NJjN(JsLf+0#&MTXrt9Uq;)b>^}*v8 za?!0vw~Bk?#9roP6N?6TcFi^Sl&Qg|Guo5h?>7j5fqRS}m-FYF~pRfXQ+3p-$*(??muqzTg| z?iO^lgCg;J007{bl)S(-cYS6kL|}K>!or`8pol1_kdB32AS)n(7;KWeA~UIdk*n@; z?hWo8F5NfZ=f}h6$HVVG?~h5s5ra^{oW(;9AOJd06~t8|(W!>Hj&XvF7~KE9e|!8A zHz>tejR1@QMjXZ{8ghz;3?aEyD{#?m-dZ^y1GFPCL01j$b5>`aofrs=tNvK}W} z!Q=voF{92zBl=7Pxh)s7x#&ziv*?@TuR*w3&`Zfyc*npz!ScXT8d7*Y!iFD4c|Z2l z*wFK->w020UAIqVQCC{fSN9c7*zYAfl7P$vMar6Gud|eP5o)jbozYp?;aq)$Z1{t7vdIc?tvm zkSeRoY5%0`T*Y3n+!Y!tmXi6ZcOr!PWwNFT+%L#9k146SvNf|R9gU<>8I+s*zhB?~ E12=$}`v3p{ diff --git a/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA256.golden b/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA256.golden index f7e09eeb5c841acef818088ab7bdd223f2522ee2..ade85d7993c457f8336ce7122b73b6826a43a534 100644 GIT binary patch delta 466 zcmWN{J948i007XLlw4q&JwRq$fRGSSxZoG_aadwxOxy_x@COVIvH3Jv&lWj=+Z-ZC z+_Z1r*XP66=fk&mdz4hnan5iKWr}5}at&%3l_jRh3d4+2#8gc|=zhNadMvmiV_NWx z=Tv3dPX-J^2v8>F(vKEY$*8Iq_wU>8!;bpWIB?MeAyt!gm@$&|vUw$O-t2-rrTo|= zCfz7eQEfY3Cj&Dq!VV`zNO`twz}|2e4cYvf~ zzxSpQRig@0a5?k`O%@R9INFt?^5VFimu!<+8po%VOzhex)heUJ?=NBp(8^0E xG)Td|4p!&$vrBwI*Kj&}6B!%Cp*eMB<`VDX1|$ry5*YKjFqgNG-T(gk{U6=`mNozY delta 466 zcmWN_J948i007XLlw2Uq9w0L*&<9DVZ~E67r&xfzihi~Whl%|4ZlmafY1PVe4(Fg)eAU)M$%!S5z%JhWX+uP&QkAxn_oTG@) zh;Sxo!XhYQ4u6{Ih(SzQ7T>>bhmR%c1-Gw#>jots!<}#KJJ=4*)v=b7trfP@Ro}3F z&pcA~c5ON^QS+(e;FOdn#pEcqjVho8m9=(ICF`Q0nuVE)>3;Ehg<1%@vYBlRh)iBX zSsW&kypHvi(}(zcQ9h21QC1=7kZ^;!ZD$=og;Dr*-eFR;r0ho{Wpr`3=>GTLum3a4l#2iW diff --git a/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA384.golden b/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA384.golden index 020593939c59e3048d41e1ee733eb3006779b33e..156adf009bc19c63a8db9d446de3623f7b99052c 100644 GIT binary patch delta 466 zcmWN{IdYp&007V#ms}uC4&WIV|FeCdP=T<-rX?(2fV#hcWEK+}AIYYTD5hTeP*JYg&2{K($8DfMeOw(0Gxu0%7o(rx@h!mXi zoM=pcWRc0TEGiV{@Sz1!DbbAL{(U=sC@46Xjk&Hi6SgV@TO;tog%-1BC8dtvMt*2- zd~u|E(Dm%i#9$Jk*|eu+Wi~=pSRTB-On#XEN|FuFtd?&jN5@_oh(=y_`_hrN-Ic9J zQFXncTkS)DwCj?>ks#9$J_z>Yswj@N^16y(d~P<)$>h7aTOE`Ib&NN>vOp}SZjz}+>S%4 zyM-TTN%VR-1`01LB9LV=**1x?{%Lg!WmTVGOofWQkH^l%<$yV1hXW}(|1 vDl5a&Nh+N^?}f4+#ws4%q(@l delta 466 zcmWN}IdY>w06@_yhg@KiIe@DOpn<08KmkH*7G@EW2FTc&Mb^fS5|3&EA3&)O;UkW+ zUoZIIUoYQZFF)q}HOmOfMUllMPXU1PFI_?ON-W%PV=YpcW=V^5gHn-~RzlWtH{- diff --git a/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA512.golden b/pkg/integrity/testdata/TestGroupSigner_SignWithEntity/SignatureConfigSHA512.golden index 33c04f7b38298d046b84339b805fef5ae4f07649..f1d9afadc8cb5a4d1e2641830bd23c9d2e5bff60 100644 GIT binary patch delta 467 zcmWN{y>g;J007{bl)S(-_W+rpU}a$!3JU=vAc_Kt(k;6z2O0@Kf~3hgSL6X~^ALH& zOZ(0D_4)Mm`Sk7Fp8-Y;WfWylCP;>uX;4dv45%in6j4GHiZxYH9`*g#GiR!d2xlqF z2&URko=^zkL`gvgev}h6C0OT=?|c3+TMjvwxNXL>pd6Z+cXmzXbg`uuI9yItVh3Z3 zeTR10oFw)67`?-!PlnFA&6lPn)OFNVO{{M0qLZ`bW`Cr&aaH3Ra_4P=<|UR&kvUTK3x;pTl%^03-%(>K~Pp4mGIZu!mKUB%H~d(1Tp zbEKUO8mnZpF`u6zV9)Nd_ZO_c(ZI_!9!F8E-w-2SYXk`S3q2}$#rg#53tQgOR~TLEU1-)M2IB_E1;J0^W*XQ{wu5^1ffvK zN+Cmll@b&@Mv(t)pbCH&6;Pw+&!hP?t5(BouvuYWwY_a(*xh8b!i(6~hRroQR*xjq zL}limxrHeUfi!HAIE>R(0VI*JlHtOd$wdcyhhqrZuGg5hz zA9Qpbx|6*&=|-bg21j$xelnTlz&u+Xqj~7eYJH@Guai}t9@C-KI{i);Y;UHK%wM~8L=ihHW_gPW4rYmHeP&n{9-eZR@;n@g=bL5;Dc zMdkE!yCyL}rSK+cZ78IU=|WEpxrxx;;B;rfuD xvWA>&_qcHYyhsicN2L@SZFJDaloAhD#vh2weRAYl6b92NGu@fs_Wb+r?LWWfn1=uW diff --git a/pkg/integrity/testdata/TestSigner_Sign/EncryptedKey.golden b/pkg/integrity/testdata/TestSigner_Sign/EncryptedKey.golden index ea68b45706bf2af24269ad56572abaadbe609421..fb72e4a19a3185d8cc26bcf05053d85eabfabf20 100644 GIT binary patch delta 296 zcmZo!z|?SnX+i~4fYN3~;WqwF0!d6<3<3;b@JD`gj?k3a`i$bjVkV%-s&wZh1_mYu zMj)G!L6G49kYoX}6@VB7enKdQk5KwQ6cj`GbD;ETDE$~pd!**%x8{SLP%p z6)SS7GgRD4PP%dE1OrQK{mXNn32Z_FY)Niy`wJ@7R#Zj52}q-gO`C(fI;yxRGg*Z R1v3M~YbXy)ZR};@2LLutMrZ&4 delta 41 scmZoTz|^vUX+i~4h|p$5;WqwF0!d6x8{SLP%p z6)SS7GgRD4PP%dE1OrQK{mXNn32Z_FY)Niy`wJ@7R#Zj52}q-gO`C(fI;yxRGg*Z R1v3M~YbXy)ZR};@2LLutMrZ&4 delta 41 scmZoTz|^vUX+i~4h|p$5;WqwF0!d6qcTAN~3L&D)E`Ppw)t1~wO~KW>~HMt@v5 zYkA4o3Aj2kfuP-uu_khWyN>g^nYB?E()un2o;3v#3 zH7VMX;97imbvA%OEteE+$E+z>Oz&U;&xoc=q3t#dQ9QO3Gvk%rBAxXoLCc*Mb78hH zr@U^aZu&LPO^k*$zEv96v`&D60_r#S8?2XTmj<-s(V09ec4h%rJoYPT;+Ml_<*1|W zD3}VXN?1)y%Z$uIB$`2q$KzttlBPHZsL_~J9XKoJ#GpBz^h?uWx!Wshfqc}P z@1!iMsSXCoZs1(qcX~NXBDAB)*a}*c0JlBc4ZV`m9EEMZogd2;+%79Ai_O5=#B5k% zIZqC#VyBbHd(E`jmq*z?JZKG#o(BWDF6BC~y0=H|&G5{mzCI&Y5#zEX$Lj^Dl5Q*x H?w|h;=o0nn delta 594 zcmXZMyKd7^002;kIv_8gsw|zVtO3RLec4DIoR^)4Q@2hXr<8p)O>h0j>p%Fo6|S)j3l&84Jh)jbfc)Mj(a^ z*Wc7*8u4)3Sse}_R?NMvkZtvQOy)nUZlUmCQ&lbVby4I?0Fwi2$@>W!tP3*XT zt2Etd;kYrqOqyvvJV<-vww1!N>*t|G$PQ&yGZ|fFeo|H`S**BPU2)e zQj0tlSqik!)F24jOhJaENv2GBAcKpdS+W#ayR_((F+hM+cKHMDe&7F|->tLQt+Uv# zI8K3eaKXDT9@%jz7TZ{v+wr@PzWwx<>CEzv{n%pnu9?FC#K6*`UILfE)5W~9s1u8E z&fEV5-b8*M;Yayq;6F2$80e13lN;1m=t|MBAKvmbuEF`wUW*K08lpD*8AKRt;4 z_~g9h1&^crQFLwf@`qq)9c;de)>lsdUIyUbC|&5m_py&3{`}L@3^JHC1fC!crBs$N z1gO!_z?^D8NO&IcTw2wMnnD^!!!#oZEQ2+~6HUMd#~Iqz*IN!g)X7Nfo4P;R+S&3g zHN|o}$UubAS)ESPD9tRM$Baq@gF!5ZXu?A*5RM3+>1l%z5J?fFE*ha#Lr7twLk=?Y z)NON?YuFPr=CYvr#*lnxrWEobMYQ>_T zG<(#zWJ`i;@!{3!5C-*pO0*rbu3#~p&L0PDcT&oS zx#EoSdfA5Q*F86Rd{pP##EwEyD8gQi(znUR_C2Um> zyV|ybsj#MmwdAD2$Sg#n8I*ZEDzz+WqBK~dz!Ha=&1ubn(@I_pTBGrxJUOcL`Xw!p z5Bsz2v_-Yl;V{(;oU40IKW|Bdb~G7VL3rk zo0eE9kbSDu?IsIeD`O7i6R8007|D%22Viikc-;| zxFc}b_{-zFlh4)B z&#ymzJ$^X({qp;#kIxU3U>Fbu0H{I>) zBhoZeKz50gs!FxG%>7HrjRbK3Lb2y&m2b47+%2ni<_&lbny%BeqxpL!w?G*7x3}qX z2={Rw>f@H%z#5)(8rlKFhTz++D&&SmkiE0?&a8+h<6dIl`ciXyoxq|D7y2x-+aqAc znbtPDJwF;4PT9fKEyE-gaOO2u+`zM80B&5pAX!QAVk_}T8;q_lE`*EqI7Y(Tf4bw& RnQho-PTv^ole^Kwi$7YVy{!NM diff --git a/pkg/integrity/testdata/TestSigner_Sign/OptSignGroup1.golden b/pkg/integrity/testdata/TestSigner_Sign/OptSignGroup1.golden index ffb549138a05190a331b916dbb4a76d23ae4a0e6..838cbf200fac9e9f31158662ad554a8ff160613c 100644 GIT binary patch literal 304158 zcmeI*Uu+w99RP4AYX{2)Ed!pAMiz-}Qp<9V|3|85{xwa~WNFf*O<^$mY{zMnIJMI@ z>8L2ug!aHgrwJh;9wsEv!~;WOFCfqgLj2Lhm;?`q2ZZ2d2n{v~2{9qcU1N7!+0dxA zDl4C#^7GeszWe?8+%G5J+2>0n{(G7oJMfvwfzh#{M39XC{v+MC`smA-FJFFa|5FR` zYkOM@1nmWPZ$0_;N-LhDDLE02lx;rWryt?5MTK>uoN&E75{Zg1R=H#$eLUD|jvx8uq{ipR>;fpoFe-PReP ze}1$zz0C(wJc#0c7)Y({b%Vo|fpp8(M%daTJ<)DKd!N*b+k7Ck{uvTMU%UO{jTG3q zKiV0!hRRD<_DWA|P2JU+*^cdV*X?*C8~Il1iuXu&?)cOfZ{NM+`D4GEc=2m@-20c$ z{r!87yp?q=Lx2DQ0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5)W{Q|E%_pcY<{!*1lfB*pk1PBlyK!5-N0t5(bCxKe? zR5QL&^*0xXO7VTq<9iKvBtDS16g|ebN$!qvoc^&D5-+#n}P5k`RJMa2Pyx>C@5(n=4#g8xj@Zw`%dHnIGj?NtJOx*eSE#KOG;h|O)AG~tU z`9$Kot?Bo-R@-^s`w|_y6LYDT#;aryG>UpuaxD}4S3!_j%e ztrVX-jMME=z7XZOyts_G>_>k8hZ8^DHFELk7ry+S%#&aGWi;z`skc^Nsq_}h#g*P> zBkXN1ReP7~^|fmI{Nn2tzRrnfKeq3c@Bd_C{p+^}-?;eM6Su_ey`xpuYx{AX#lPWd zZIf$X+<)y1(*y_*AV7cs0RjYWfI$2GdHh*_K6>}R^{M|2s8|&Q2oNAZfB*pk1PBly zK!Csv6Zk~y1F-h@`9%T*2oNAZfB*pk1PBlyK;R}6h`y|Q6ZT4%2oNAZfB*pk1PBly zK!5;&*9f$~Xb@lj+Rp8HHzK|`5Y@6fk?4=EE6%s_R=u5x_qG}kUz@PA^;{tEb_!hh zd{o+{{fYM2fAu=>j;rJEdh6@DX2mzV7W|sUOx{3&OY#0EO7V7Y?|O00n@}vRA(~EyRO##>iCQ6kAG9)dee8FF3(@@y4E8=fB*pk1PBngxdh_t|L;h2 zblxAu_<47tv-AFFB7VR5p+r~ba=p2}r&>R~THgAttY7cCt)mwIrvLrx8|%?B5&;4P z2oNAZfB*pk1PBlyu>A$%T&9-Z!<9UGk*8Sb7OnVlUN9l7#i*TG`5*55sQ zaG)=f?dp2C=S-#1T&l13^e6ZB)GEbtrP0&>a8G$@vC>@c>F;UQiqV4o*;J-l42sEg zF<+?$VUWrsE9F$Bkk8}_g-SVDPFHi8uu{mS%9Ua&40GAAP{<{NTp<&NscN$4{NA2= z=|m-5Z}#+m^5LFFWx2S%bfz*^?&%Nq_LM8lu(7nZUT+LvQ*kPrN*BvPvRn$v3lwuE|m+p zu$(Vdv)O9-O}kO37Q%ETQ%Ru+(;6k%-aAIXJ(_3kr98TwsA4(6VCeCK|)Q;8%)0xWX;jyu1@8a>U zGvmvn`L$YZ^MP|K!N$x;-|%vMab~_WJg}#fFP#g^mC?=RwIkKx;nTJG#lgnp+IVuP zd1mA2+S&1u&7rZb#__?~#pX<7t@qUGOz!B!`b>FYqp&enI5~IlNT$(yY+@x@ZzKl~ zWQG^cZDhw!H>U=|=H%ww)QN@ip7~PO=HdCx!@XxG)6dBgPAjnM{2{92f{;L;|mMD z2O4t&izlZ~4V?@Q9bK(1HG+-l+0l`O;PAeEUHi_J&Mj_j%aN(!t2=;Kx8%P8IPUhu delta 655 zcmYj}J8#oa0EKDg0eNYuct{-@+1i)>9?eSYw4R>vY_9yR$N%qF{?^-xmY@1@*
g}p*NvN=KA6I>`c0C12eJaBCp6G0SYP81v#%Pb_E;4lDga~yUM zgCxvBe4T#!QW7XW=M>)bwniC;;@lI8BQUdBL-=7dmOc z_50%<)}=Dc8~AkCKP)Z~ErwQ9M_Q{=nO8!6s)F$}(#8jt?%HGRSjua5Q}PVWnjm)2 z)q}<Qq~e&T2l&V@KHh3%ubA7*(3M-#&3N5nKE6_7S6 zX%Rs4kc}iUpByCi0c-g*(*zzQ-2{{@vu60ir(&W5&uh$1qH&8~ z1c|3~%2pA|uv;z4OUM^#+bHLrtLjKF=DJcHq(Qe+4~-L>EzOQXKFz$5GKh^z8)!i+ zSF~E)_M57iRUx)AFN|my_lpx(g@cv@jx8lcafab&#=5@TY#;9L)BDp-AkdHgQ0r88 S4b|8+8)`@Cp0zKi+rI$>%*%lQ diff --git a/pkg/integrity/testdata/TestSigner_Sign/OptSignGroup2.golden b/pkg/integrity/testdata/TestSigner_Sign/OptSignGroup2.golden index ac5ed71d0da99a3c9262268cd20fa4893e22081f..8a0f4fa37372149937f42f7b35d41236eaa95ee0 100644 GIT binary patch literal 303959 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 Mn>#$Myv|(v1zKszApigX diff --git a/pkg/integrity/testdata/TestSigner_Sign/OptSignObject1.golden b/pkg/integrity/testdata/TestSigner_Sign/OptSignObject1.golden index 0d072c7126af5911a2fde48bd574339b66c43fb9..87aaa135dd753de1a7dd11bd21b0a0e14b038bfe 100644 GIT binary patch literal 303959 zcmeI*U5H#)9RTpVX;SUBnppKo(CtFCkl3A%ov(#pc4uclvYX9*CD}x)ozLthyE~hi zO*YvYj8LQxKBN>8#D^lN#Rn_c7e#3l@q=P5=!5tmqAwMxwjhW_jQ8%$q;0H%!G>+} zJM5YNoICg4bI$Lcz0AEccWw~;_cS*?@~K0EqvQD?7LWe^E#0;H*eh4BUVZ$))5oLN z_O)k-b!Obtdh)H6cD&e%U%!86XAY470RjXF5FkK+009C72oQLS1$G_?g08Nxk}$u# zRoA7h$Dng~KEIEIg0Jl##^}^TLUQ?E7u0n<#u=5XMq0k zp>}zj52R=iMg1_4+S}_UhpmBhM{6Ur_DD~5TF}`iwc|D)NbP@yAeQK~U%Z(DyAFgq zqxMjFd26rqWUF*68eL)P#Ll_vPHerpeIBDd(!D!B@%g*=?0jM2w-YaY<(`lH`7?j} z?xWkMg<3*@009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C7ZZCmXpa17ew^xt#mH+_)1PBlyK!5-N0t5)$egcclGtKBm z)!#UoFGcq~kM1?x6}%_75Xid!7J@}wVj&n@|WB3xpw?RJC0SCm+L*X zMt!Ac?!t1h)V#0zBf4^@rUocch8-rkzY|Iw8nTz>pZPdxGTvDuj&!M#u1@y$J#9&T6h-mQDi2f=sR z<#)Fi+x5V^g04NmeZOo^-+Af9@W#)7YL^581PBlyK!5-N0t5&UAV7cs0Rp#yKu_4m z17Qx&j0M>+zdy`Tip~i}Ik?oyJz*$5J6vjpc}H;d>fB$tw$2s4@crTNykRRv=MJNE zcbG4QIa*(|j%eMF{_gjuezLo8`I#5L_>R<5U-(5h=?$rGvA$C6D^`jtea%L>uens~ zTdvpFYMt|oZs*M z>nA7^AV7cs0RjXF5V#2fo%iR_XZ_jm-GA#-|C>;;DhLoDK!5-N0t5&UAV7csftx1q zvGxaGo$vFD1PBlyK!5-N0t5&UAV7e?EhrFvS@#y~l`at=K!5-N0t5&UAV7cs0RpcR z=zP&2y8gA3JJW7Pd}%POWls}o$32>d?cY} z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyKw#Smd^Ac!h0*b;p6Su)p1JYSslss2p~BqU;Amm%#qP0Ub8(<&Zfr1-N_TfZ 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 delta 654 zcmYjJJ#W)M0HwtP^3qZSNK92$K(X(9cXp);#fkIT*iM|pu@_|f{1H28;>JmnF4-6n z0*S65BsQdqYz#;&42&$DU}WVFpo&5nc+&flp5FQAo%0`?&z2i#{ps$Lt@qpRCd*v= zhwb%n=h6TD#c=2C^D}1s`1aF{n`c)m^ZJz=x7HVTHkZuzcOQRVe*M~FK79Lf@i)DE z#e7{+mk6GVArwS`7pNZ)h#>N$fD1(Eiw-3;z&rqwPl3qcK%kE3Vu@l(1T0XTdypHu zvF~N2LFiAj++J=PIRN236cEva5D>u^VBkp9M;J)}Baf#NPkewp4w8ESP|xLDkpe<5 z6$QTIh&+@KJWXCR;i_m?kAu9~E*|)mUTDhhu)`lBX@nI!QD!Gev0?btC{0m!p&LMN z)*5n>wTNuhd9~YR#l|9N>#ZQfLSGx2B8f+?rBzQNyH!S`pwb@~`V-4S2Xjty!{*Se zq@Ywdh`4Aj#kSsBu{}}_=iPQ!Zs!wTPRmg7(k7`7NM1G6FiTY|+_#glRTwn6I5<&C zdbPNm1eRTtTTvqhtQPw5xYvbK&48Xxtj2tn=IO8`*sxkVyd-Y)xK!fp&a&;PW?q@h z8;N>U&cMQuR-jN|JEO^>2($t;kY!UR;xpOoBy~~NK!RuGiBXyvb@8YlPozxe%C)v} z>~UJFqM%{uOq)HnS0Bv$5Kaf4Aa+uen4xtD=;%nYgvdGG-)HwhHzDl9KTy=tu3pi1 Ojao%5bWXK5%#Gj8O39M| diff --git a/pkg/integrity/testdata/TestSigner_Sign/OptSignObject3.golden b/pkg/integrity/testdata/TestSigner_Sign/OptSignObject3.golden index ac5ed71d0da99a3c9262268cd20fa4893e22081f..8a0f4fa37372149937f42f7b35d41236eaa95ee0 100644 GIT binary patch literal 303959 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 Mn>#$Myv|(v1zKszApigX diff --git a/pkg/integrity/testdata/TestSigner_Sign/OptSignObjects.golden b/pkg/integrity/testdata/TestSigner_Sign/OptSignObjects.golden index 17fca3c1afee9c1c6c9f6b65318ae59214340573..ebc2c8b3dee655378e07647430b10d1f22bf5209 100644 GIT binary patch literal 308055 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 OaNcgsjDFC-`M&`uCJAx? delta 1218 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 OaNcgsjDFC-`M&`uCJAx? delta 1218 zcmZ{kJFnwJ6vua$6evR4hX9FNtX8)*$R5wwGhXQmIf)-hoWx0PoJWIZJRT>`+m7>U z(rt+l6e~IkM2EC+5l9q>67dDLf|8amfL3JLEok;%9G!FY*O89SPv`kx51v1H>$Agc z>*oH&le^#FV|R*$Td#HRX7=FY|JPs49(?opv%<|M?|pjv{#ZB|!Ef8bpWpuS_j%?&cMCuN@%xMavLC-He0lrC8Ac(~Aw&cL#3O;B2DQ)-iXbo| zlw&S*psGg1RifwuaY~qOaGhhMBd%Y5c)4Ur6mBY$ILbDck1w+^RW<#wCNK#hR56MW z6x866rfY_(Ya!qUz>%tj3d9$x%0s3w!d1-AQ4VI4+euYpj{xqk!rf9G3?_ZvASHaP@^w6DOM6z-S3znsw_Yx9%d5u1 zfs;k*PFg`j(23h4M~l`-;=93=f#G#ySzQCU+u!-!C2OzbG_RkEdvje%(ZL$zp^NcW z%Z~EO>tut~;h5s_G*XY9sM}2)7X}kP`hkZRNBDf>}|i!9=lx>`0x`EDsLH zayF=m9Lho0@@Mf}&l@mFs+&JLF8uJ$Dbzy(REl*< z4Wv>92u#l>Wr`XhqN_9{6hK57Csd6%QxptB%%Ms(8ioKUZ$w4aC<_G@Oc#(qLL&h= zJ~uH!Xa01iK*}h*P=G=;rmF}>h$1S4ID^X(V9G00Nf)?F* zJ*<+d7rJfHw7_mba>?#!8&o&T2^)_)wtlU)idLrje$%c_QWQG8(laZ)eb*hJ&APlW z$YL%JChD%t^=#LdxN<1X&9oMFo!XoYXYDnpoQiZ3uO&X}D~h~~jjnF?Wo^A}Pxrtm zxqK*#5r}tvG~UOM zjxdI#GzB(>lX0wa(jbKi4GeA?XOA2>IAP+f$&=TI2L&=Q2u)^QC(w`pwL%!=Vj$QF z=N*p#vZVF)Ra@A=)?4cyrcJV8MU%!7aYKKa}U z>Vd$*?8FH^e17TJz0tVgwY|V}_hDT{00h9yw4MP+z^myzJFP?0vB$6f0zZBK@$vk8 z+xL6lUwy}I$8kfX<6aIGhK`B6Q`8wS_=3^rH@jf=!ub2g#QI!teh$U1yxba|ejr~h z14Ke|;N8Xj3n%tYuJ3@@*$;1Dy}o|q)@1UylFtP|aI){w{LZ@n$I-o(r@ZjS;7ibI8zje%vdZ#5HtzHU`bLW z$eT7cImLo3!wa%33dm9IfQKnGQxzrUmvRitP{Fi9gfzZ zptQQ(PL<`8%~i3PFK3-d0y!(W0dY%%2s`K}s#e}z6|t?=nCRtjO`~K4s}9@eJgwMv znLI1vWT7E@gi)PXrdQk2a(P4Trv|LlWGfa^kK>AvD{sSkvgIJ7XN)PAjwY?B!4;cG zUFFPJZ<80aNP6R80KoCq%22Viikc-;| zx=&LLMd3V^ICp#r#%SqKrtGJ;fMSW-h7 zQW2=9vdm~81{#x9_FTwA-`6C7A-IztqJv3r6zS=8lQb^#+;RKV(Bo2M`?;?Jjcdr<9%osLVTrf5vP zy|d@Nx#u=^Vgs+Y<)+iu%{U=Va1bQ3x4sE>nJfD+)<-j9+qfb*=xVY9te!=x7BjEL z)XtSjoJ^MX_LhzdF<%hW_3)?^wt0RXHNZM8%4rf4*Be9;o(*BF<>ky$(JG4z+$vUT z;+i-l#gtC0-f-UEOpV+;bW1F#s<#c3?jl;3Wk_bq>Pogs8(VH`X-+|uDn^;nd+HekH~FVAWkOkkGVd9#IX;xU4z}8XK*0!)Ld&QIe5~y^9OsVl&S|;r&0B TW1bD#gR@bm?dapX{==)kN%y_N diff --git a/test/images/one-group.sif b/test/images/one-group.sif index ea68b45706bf2af24269ad56572abaadbe609421..fb72e4a19a3185d8cc26bcf05053d85eabfabf20 100755 GIT binary patch delta 296 zcmZo!z|?SnX+i~4fYN3~;WqwF0!d6<3<3;b@JD`gj?k3a`i$bjVkV%-s&wZh1_mYu zMj)G!L6G49kYoX}6@VB7enKdQk5KwQ6cj`GbD;ETDE$~pd!**%x8{SLP%p z6)SS7GgRD4PP%dE1OrQK{mXNn32Z_FY)Niy`wJ@7R#Zj52}q-gO`C(fI;yxRGg*Z R1v3M~YbXy)ZR};@2LLutMrZ&4 delta 41 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 delta 1222 zcmZ{iJ+I?L6o&UMDUgMA9NS5p zCf$|@fzXPM0#P6#EnEZ=1)@a!fvupV*n6&lRMwub#F_BTQB48Cok@Qb#wo%PcQzjefjaT!p#Toe0Xv1*?*l6URo~SzIkz9 zyM6oTTQ}Ofzw8RXfBn;+=ed8~Dg5}`uP^?szW==N*~Q6oRm@z15Z17aJuXzFAcg4y z2n}(Kda5Ug457|Fr~x9dM>Ut|9`RI6ut%=myIQ*;XQ>(ZJV~z}T_p<&74k?Cs>Tq4 zD&`mos(V}^iVlgwWKWk>4iyHFdI_P&T;OURRK0Un1gBJ!k*=Vp%Wn$)$#itzFGtgo zQ>-LO*KRYT9Av;d&JCedgnPWU$Nl1@OT%(9&+SHYHI-9Yk4$Gh=pLj4a@J9v4}^8S z*IPnf5piC%UhCz@L8D*1T^Q51^>WyKLKNm(3t_O6VlXW-DH}hqVo< z5|oECr(V}{CqYdOc9GSxoV@Cpoe`@icpQY|ReiT-qZB094r%uFVJ7X8Wa<}D9HrSL z3>>@P^L>3bPy#Kmb#u=|&B0Q|C@PVPmT`n76kRBQa0SOqW!(zvE%^+K;o0 zJ2SlLKr5^3mR(($6XZwO$kr@bDR$fR#lp!(a;ns6E(hh_rWs!osbtOij%rv&C2xde zWK^@QnC)3HbB3ngfBaZ_yq&MP^!`6#bpwjBqVU}tCq|ei zL#h%=bqpzxg-Xvabphm9BakwU$_P`}(Nwl= zRj?Utz$PN~FuY!>rM15*w&pnPq>W((nij3}dP}!w%wx&1<7MY)hYO`$?5?qq9^nLP z-ZU78od5$`fqheHMR{aVc$f<}+G+MKszo(THnhM^PEy|SIV)-QqDFgoHeZA#D_ymf z4R7{0`e-oEp@s1zsO~rR*5M8~ z%$t=p9PyoP00rP}6g48zohHcQuE|TsJaVJ?sp)m4`f6qk)7)roIgLrkT4NdI!%-_W zR(o4(*4mjrt?a9d!6NRpdrdNhcBr@gUWuE_iknQe^-zfiVCuGu_^|B9)g57A QWtPK#QCUxo?JH6F8%~CP=Kufz diff --git a/test/images/two-groups.sif b/test/images/two-groups.sif index 0555d09d3d1a36b8d60f4278d54f9818ccd24aff..36701ad535385134211bec437f74d567a633871f 100755 GIT binary patch literal 303104 zcmeI*U1%Id902gSYg+AxCRTkC^eU(YF-Zj>2x3ZWZ4g0?)F-vMrZJYJS9=j!P&h%P zkC7sR_~46Dd{Du@2uh=f9~4_bAH*lomx>fE_+k;`Om;R+V=WkLyu{zox&Q5UcW36e zljU~qb~l8Jr@?`3kKe!f-hnNlcT@WJm$Z8Cp)=Fd(;>&(@&di(f?dU%cgAykwuleh z*ikMa5+Fc;009C72oNAZfB*pkmsp^qKZHsp783I>Gi9}AUPF0${&2OJE>G}hW1ihE zA=Njv<3eK;?NZ0(T#uQKl={kSN1Dvd%_Bg+-;k&0jTp5XO6o+Z9Xir~vu9>H(u!gy z6i1}j%8Hc7q#WD4BjrDa(0hAXe~|zI0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV6Tr3!FXi$LS^C2n`@WfB*pk z1PBlyK!5-N0t7B9Fxq^onI2UA<`Y}$>AC0W>F1SjRhWve=`q{2m{a<#2;oeQ(>XQs z^s6}@&+&&Gx9=VsYt%;eH^ys&2gio$%?)dA2?xI2RsZIr&qBweKb{!axoUmas`|DU zj_o^m^O3$oJ3@V=wkmx7*vjj#OAGF7g>4(Z_;~8W$roQaeE9809(u4E)*oK+R#$6h zF5>E$XU>Q4UY@=(ueNgI6`|4H_%qgWY!IVR*$h8=Tj%}?sW3Gnj>A{~XGh>Bcey}x;8x|>z z9j3H4=2pyUdubbK+s}XZ{hm)d@0mP$>gCJsIP%iTIP1LBGujy6-7_>iG~UzPzpJPD z9)zvmYT5FkK+009C72oNAZfB=DIC=h?Fy9`^UNdyQGAV7cs0RjXF5FkK+z#M_{ zhX(2T*D{y$79*bC982j6;m&wnabM0wxz%uau0XmrVP$?V5coF*TF=F;P4$Pe@1MI4 zyfWMW7Fyn#c`N?iwczs>Gr5QYQ|b5xe`?v1Zl1~$AV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U yAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjZtPT)^(+N$&b delta 74 zcmZoTAk=bzX+i~4h|=al(Kh}~0!d64c1902gkRZ-hQ1a*&tlhEiO6hW*|L2xX%r?#P%#FHk1fae ze_4E2zP_^d_35!oFIGQ9RbNyWispQ^Hdkv_TT8dAtvmHu$UW_bnwf+12OYNt3D(o~~uFc)r>AKbVD#gLW(<2oNAZ zfB*pk1PBlyK!5;&gD;To^S9ss|0s9v{}2A2+d~2b2oNAZfB*pk1PBlyK;W+g;`w_) zfB*pk1PBlyK!5-N0t5&Qxq$osAwR&nM}PnU0t5&UAV7cs0RjXOM zjxdI#GzB(>lX0wa(jbKi4GeA?XOA2>IAP+f$&=TI2L&=Q2u)^QC(w`pwL%!=Vj$QF z Date: Mon, 28 Mar 2022 21:41:36 +0000 Subject: [PATCH 02/14] feat: add OptWithExperimental Signed-off-by: Edita Kizinevic --- cmd/siftool/siftool.go | 14 ++++++++++++-- pkg/siftool/siftool.go | 13 +++++++++++-- pkg/siftool/siftool_test.go | 7 ++++++- .../SifToolExperimental/err.golden | 0 .../SifToolExperimental/out.golden | 19 +++++++++++++++++++ 5 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden create mode 100644 pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden diff --git a/cmd/siftool/siftool.go b/cmd/siftool/siftool.go index 84e914f0..774bd545 100644 --- a/cmd/siftool/siftool.go +++ b/cmd/siftool/siftool.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved. // Copyright (c) 2017, SingularityWare, LLC. All rights reserved. // Copyright (c) 2017, Yannick Cote All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the @@ -16,6 +16,7 @@ import ( "io" "os" "runtime" + "strconv" "text/tabwriter" "github.com/apptainer/sif/v2/pkg/sif" @@ -83,7 +84,16 @@ possible to modify a SIF file via this tool via the add/del commands.`, root.AddCommand(getVersion()) - if err := siftool.AddCommands(&root); err != nil { + var experimental bool + if val, ok := os.LookupEnv("SIFTOOL_EXPERIMENTAL"); ok { + b, err := strconv.ParseBool(val) + if err != nil { + fmt.Fprintln(os.Stderr, "Error: failed to parse SIFTOOL_EXPERIMENTAL environment variable:", err) + } + experimental = b + } + + if err := siftool.AddCommands(&root, siftool.OptWithExperimental(experimental)); err != nil { fmt.Fprintln(os.Stderr, "Error:", err) os.Exit(1) } diff --git a/pkg/siftool/siftool.go b/pkg/siftool/siftool.go index 08c0193f..1e0434a7 100644 --- a/pkg/siftool/siftool.go +++ b/pkg/siftool/siftool.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2018-2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2018-2022, Sylabs Inc. All rights reserved. // Copyright (c) 2017, SingularityWare, LLC. All rights reserved. // Copyright (c) 2017, Yannick Cote All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the @@ -35,12 +35,21 @@ func (c *command) initApp(cmd *cobra.Command, args []string) error { // commandOpts contains configured options. type commandOpts struct { - rootPath string + rootPath string + experimental bool } // CommandOpt are used to configure optional command behavior. type CommandOpt func(*commandOpts) error +// OptWithExperimental enables/disables experimental commands. +func OptWithExperimental(b bool) CommandOpt { + return func(co *commandOpts) error { + co.experimental = b + return nil + } +} + // AddCommands adds siftool commands to cmd according to opts. // // A set of commands are provided to display elements such as the SIF global diff --git a/pkg/siftool/siftool_test.go b/pkg/siftool/siftool_test.go index 20c40647..d6ad263a 100644 --- a/pkg/siftool/siftool_test.go +++ b/pkg/siftool/siftool_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -82,6 +82,11 @@ func TestAddCommands(t *testing.T) { name: "SifTool", args: []string{"help"}, }, + { + name: "SifToolExperimental", + opts: []CommandOpt{OptWithExperimental(true)}, + args: []string{"help"}, + }, { name: "Add", args: []string{"help", "add"}, diff --git a/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/err.golden new file mode 100644 index 00000000..e69de29b diff --git a/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden new file mode 100644 index 00000000..2d8532f5 --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/SifToolExperimental/out.golden @@ -0,0 +1,19 @@ +Usage: + siftool [command] + +Available Commands: + add Add data object + completion Generate the autocompletion script for the specified shell + del Delete data object + dump Dump data object + header Display global header + help Help about any command + info Display data object info + list List data objects + new Create SIF image + setprim Set primary system partition + +Flags: + -h, --help help for siftool + +Use "siftool [command] --help" for more information about a command. From a0e86dc315c2c2bd906cc363f6efa2a3b3c9e866 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 4 Apr 2022 16:19:12 +0000 Subject: [PATCH 03/14] feat: add OptAppError Signed-off-by: Edita Kizinevic --- internal/app/siftool/app.go | 15 ++++++++++++++- pkg/siftool/siftool.go | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/internal/app/siftool/app.go b/internal/app/siftool/app.go index e9c69405..f0865f8e 100644 --- a/internal/app/siftool/app.go +++ b/internal/app/siftool/app.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -17,6 +17,7 @@ import ( // appOpts contains configured options. type appOpts struct { out io.Writer + err io.Writer } // AppOpt are used to configure optional behavior. @@ -35,11 +36,23 @@ func OptAppOutput(w io.Writer) AppOpt { } } +// OptAppError specifies that errors should be written to w. +func OptAppError(w io.Writer) AppOpt { + return func(o *appOpts) error { + o.err = w + return nil + } +} + // New creates a new App configured with opts. +// +// By default, application output and errors are written to os.Stdout and os.Stderr respectively. +// To modify this behavior, consider using OptAppOutput and/or OptAppError. func New(opts ...AppOpt) (*App, error) { a := App{ opts: appOpts{ out: os.Stdout, + err: os.Stderr, }, } diff --git a/pkg/siftool/siftool.go b/pkg/siftool/siftool.go index 1e0434a7..d193206a 100644 --- a/pkg/siftool/siftool.go +++ b/pkg/siftool/siftool.go @@ -27,6 +27,7 @@ type command struct { func (c *command) initApp(cmd *cobra.Command, args []string) error { app, err := siftool.New( siftool.OptAppOutput(cmd.OutOrStdout()), + siftool.OptAppError(cmd.ErrOrStderr()), ) c.app = app From cb635b6190f6243ef8090a8d4f603d70cb8e2382 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 28 Mar 2022 21:46:48 +0000 Subject: [PATCH 04/14] feat: add experimental 'mount' command Add experimental support for rootless mount of SIF images. Signed-off-by: Edita Kizinevic --- internal/app/siftool/mount.go | 24 ++++ internal/pkg/exp/mount.go | 108 ++++++++++++++++++ pkg/siftool/mount.go | 31 +++++ pkg/siftool/siftool.go | 4 + pkg/siftool/siftool_test.go | 5 + .../testdata/TestAddCommands/Mount/err.golden | 0 .../testdata/TestAddCommands/Mount/out.golden | 10 ++ 7 files changed, 182 insertions(+) create mode 100644 internal/app/siftool/mount.go create mode 100644 internal/pkg/exp/mount.go create mode 100644 pkg/siftool/mount.go create mode 100644 pkg/siftool/testdata/TestAddCommands/Mount/err.golden create mode 100644 pkg/siftool/testdata/TestAddCommands/Mount/out.golden diff --git a/internal/app/siftool/mount.go b/internal/app/siftool/mount.go new file mode 100644 index 00000000..d5fb7dba --- /dev/null +++ b/internal/app/siftool/mount.go @@ -0,0 +1,24 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "context" + + "github.com/apptainer/sif/v2/internal/pkg/exp" +) + +// Mount mounts the primary system partition of the SIF file at path into mountPath. +func (a *App) Mount(ctx context.Context, path, mountPath string) error { + return exp.Mount(ctx, path, mountPath, + exp.OptMountStdout(a.opts.out), + exp.OptMountStderr(a.opts.err), + ) +} diff --git a/internal/pkg/exp/mount.go b/internal/pkg/exp/mount.go new file mode 100644 index 00000000..8492cfb9 --- /dev/null +++ b/internal/pkg/exp/mount.go @@ -0,0 +1,108 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +// Package exp contains experimental functionality that is not sufficiently mature to be exported +// as part of the module API. +package exp + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + + "github.com/apptainer/sif/v2/pkg/sif" +) + +// mountSquashFS mounts the SquashFS filesystem from path at offset into mountPath. +func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountOpts) error { + args := []string{ + "-o", fmt.Sprintf("ro,offset=%d", offset), + filepath.Clean(path), + filepath.Clean(mountPath), + } + + cmd := exec.CommandContext(ctx, "squashfuse", args...) + cmd.Stdout = mo.stdout + cmd.Stderr = mo.stderr + + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to mount: %w", err) + } + + return nil +} + +// mountOpts accumulates mount options. +type mountOpts struct { + stdout io.Writer + stderr io.Writer +} + +// MountOpt are used to specify mount options. +type MountOpt func(*mountOpts) error + +// OptMountStdout writes standard output to w. +func OptMountStdout(w io.Writer) MountOpt { + return func(mo *mountOpts) error { + mo.stdout = w + return nil + } +} + +// OptMountStderr writes standard error to w. +func OptMountStderr(w io.Writer) MountOpt { + return func(mo *mountOpts) error { + mo.stderr = w + return nil + } +} + +var errUnsupportedFSType = errors.New("unrecognized filesystem type") + +// Mount mounts the primary system partition of the SIF file at path into mountPath. +// +// Mount may start one or more underlying processes. By default, stdout and stderr of these +// processes is discarded. To modify this behavior, consider using OptMountStdout and/or +// OptMountStderr. +func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error { + mo := mountOpts{} + + for _, opt := range opts { + if err := opt(&mo); err != nil { + return fmt.Errorf("%w", err) + } + } + + f, err := sif.LoadContainerFromPath(path, sif.OptLoadWithFlag(os.O_RDONLY)) + if err != nil { + return fmt.Errorf("failed to load image: %w", err) + } + defer func() { _ = f.UnloadContainer() }() + + d, err := f.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys)) + if err != nil { + return fmt.Errorf("failed to get partition descriptor: %w", err) + } + + fs, _, _, err := d.PartitionMetadata() + if err != nil { + return fmt.Errorf("failed to get partition metadata: %w", err) + } + + switch fs { + case sif.FsSquash: + return mountSquashFS(ctx, d.Offset(), path, mountPath, mo) + default: + return errUnsupportedFSType + } +} diff --git a/pkg/siftool/mount.go b/pkg/siftool/mount.go new file mode 100644 index 00000000..21f1fb8b --- /dev/null +++ b/pkg/siftool/mount.go @@ -0,0 +1,31 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "github.com/spf13/cobra" +) + +// getMount returns a command that mounts the primary system partition of a SIF image. +func (c *command) getMount() *cobra.Command { + return &cobra.Command{ + Use: "mount ", + Short: "Mount primary system partition", + Long: "Mount the primary system partition of a SIF image", + Example: c.opts.rootPath + " mount image.sif path/", + Args: cobra.ExactArgs(2), + PreRunE: c.initApp, + RunE: func(cmd *cobra.Command, args []string) error { + return c.app.Mount(cmd.Context(), args[0], args[1]) + }, + DisableFlagsInUseLine: true, + Hidden: true, // hide while command is experimental + } +} diff --git a/pkg/siftool/siftool.go b/pkg/siftool/siftool.go index d193206a..50ac8f20 100644 --- a/pkg/siftool/siftool.go +++ b/pkg/siftool/siftool.go @@ -80,5 +80,9 @@ func AddCommands(cmd *cobra.Command, opts ...CommandOpt) error { c.getSetPrim(), ) + if c.opts.experimental { + cmd.AddCommand(c.getMount()) + } + return nil } diff --git a/pkg/siftool/siftool_test.go b/pkg/siftool/siftool_test.go index d6ad263a..ea8ca5a3 100644 --- a/pkg/siftool/siftool_test.go +++ b/pkg/siftool/siftool_test.go @@ -119,6 +119,11 @@ func TestAddCommands(t *testing.T) { name: "SetPrim", args: []string{"help", "setprim"}, }, + { + name: "Mount", + opts: []CommandOpt{OptWithExperimental(true)}, + args: []string{"help", "mount"}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/siftool/testdata/TestAddCommands/Mount/err.golden b/pkg/siftool/testdata/TestAddCommands/Mount/err.golden new file mode 100644 index 00000000..e69de29b diff --git a/pkg/siftool/testdata/TestAddCommands/Mount/out.golden b/pkg/siftool/testdata/TestAddCommands/Mount/out.golden new file mode 100644 index 00000000..3df015d5 --- /dev/null +++ b/pkg/siftool/testdata/TestAddCommands/Mount/out.golden @@ -0,0 +1,10 @@ +Mount the primary system partition of a SIF image + +Usage: + siftool mount + +Examples: +siftool mount image.sif path/ + +Flags: + -h, --help help for mount From a15412235313b1171e174ed32d1c5df3ed35f7c2 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 4 Apr 2022 18:19:59 +0000 Subject: [PATCH 05/14] test: add mount command unit tests Signed-off-by: Edita Kizinevic --- pkg/siftool/add_test.go | 4 +- pkg/siftool/del_test.go | 4 +- pkg/siftool/dump_test.go | 4 +- pkg/siftool/header_test.go | 4 +- pkg/siftool/info_test.go | 4 +- pkg/siftool/list_test.go | 4 +- pkg/siftool/mount_test.go | 65 +++++++++++++++++++ pkg/siftool/new_test.go | 4 +- pkg/siftool/setprim_test.go | 4 +- pkg/siftool/siftool_test.go | 9 +-- .../Test_command_getMount/Empty/err.golden | 1 + .../Test_command_getMount/Empty/out.golden | 9 +++ .../Test_command_getMount/OneGroup/err.golden | 0 .../Test_command_getMount/OneGroup/out.golden | 0 14 files changed, 96 insertions(+), 20 deletions(-) create mode 100644 pkg/siftool/mount_test.go create mode 100644 pkg/siftool/testdata/Test_command_getMount/Empty/err.golden create mode 100644 pkg/siftool/testdata/Test_command_getMount/Empty/out.golden create mode 100644 pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden create mode 100644 pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden diff --git a/pkg/siftool/add_test.go b/pkg/siftool/add_test.go index a3d94755..f3c8d0d3 100644 --- a/pkg/siftool/add_test.go +++ b/pkg/siftool/add_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -50,7 +50,7 @@ func Test_command_getAdd(t *testing.T) { } args = append(args, tt.flags...) - runCommand(t, cmd, args) + runCommand(t, cmd, args, nil) }) } } diff --git a/pkg/siftool/del_test.go b/pkg/siftool/del_test.go index 8318a524..ff3f4cdd 100644 --- a/pkg/siftool/del_test.go +++ b/pkg/siftool/del_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -28,7 +28,7 @@ func Test_command_getDel(t *testing.T) { cmd := c.getDel() - runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}) + runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}, nil) }) } } diff --git a/pkg/siftool/dump_test.go b/pkg/siftool/dump_test.go index 75ceb502..46b67654 100644 --- a/pkg/siftool/dump_test.go +++ b/pkg/siftool/dump_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -43,7 +43,7 @@ func Test_command_getDump(t *testing.T) { cmd := c.getDump() - runCommand(t, cmd, []string{tt.id, tt.path}) + runCommand(t, cmd, []string{tt.id, tt.path}, nil) }) } } diff --git a/pkg/siftool/header_test.go b/pkg/siftool/header_test.go index a0442dd4..c93153e7 100644 --- a/pkg/siftool/header_test.go +++ b/pkg/siftool/header_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -72,7 +72,7 @@ func Test_command_getHeader(t *testing.T) { cmd := c.getHeader() - runCommand(t, cmd, []string{tt.path}) + runCommand(t, cmd, []string{tt.path}, nil) }) } } diff --git a/pkg/siftool/info_test.go b/pkg/siftool/info_test.go index ba7b9e44..5e793f9f 100644 --- a/pkg/siftool/info_test.go +++ b/pkg/siftool/info_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -43,7 +43,7 @@ func Test_command_getInfo(t *testing.T) { cmd := c.getInfo() - runCommand(t, cmd, []string{tt.id, tt.path}) + runCommand(t, cmd, []string{tt.id, tt.path}, nil) }) } } diff --git a/pkg/siftool/list_test.go b/pkg/siftool/list_test.go index 8e3fb0d2..951421a4 100644 --- a/pkg/siftool/list_test.go +++ b/pkg/siftool/list_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -72,7 +72,7 @@ func Test_command_getList(t *testing.T) { cmd := c.getList() - runCommand(t, cmd, []string{tt.path}) + runCommand(t, cmd, []string{tt.path}, nil) }) } } diff --git a/pkg/siftool/mount_test.go b/pkg/siftool/mount_test.go new file mode 100644 index 00000000..d1e46c44 --- /dev/null +++ b/pkg/siftool/mount_test.go @@ -0,0 +1,65 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/apptainer/sif/v2/pkg/sif" +) + +func Test_command_getMount(t *testing.T) { + if _, err := exec.LookPath("squashfuse"); err != nil { + t.Skip("squashfuse not found, skipping mount tests") + } + + tests := []struct { + name string + opts commandOpts + path string + wantErr error + }{ + { + name: "Empty", + path: filepath.Join(corpus, "empty.sif"), + wantErr: sif.ErrNoObjects, + }, + { + name: "OneGroup", + path: filepath.Join(corpus, "one-group.sif"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path, err := os.MkdirTemp("", "siftool-mount-*") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + cmd := exec.Command("fusermount", "-u", path) + + if err := cmd.Run(); err != nil { + t.Log(err) + } + + os.RemoveAll(path) + }) + + c := &command{opts: tt.opts} + + cmd := c.getMount() + + runCommand(t, cmd, []string{tt.path, path}, tt.wantErr) + }) + } +} diff --git a/pkg/siftool/new_test.go b/pkg/siftool/new_test.go index 2a2c96dc..92860372 100644 --- a/pkg/siftool/new_test.go +++ b/pkg/siftool/new_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -36,7 +36,7 @@ func Test_command_getNew(t *testing.T) { cmd := c.getNew() - runCommand(t, cmd, []string{tf.Name()}) + runCommand(t, cmd, []string{tf.Name()}, nil) }) } } diff --git a/pkg/siftool/setprim_test.go b/pkg/siftool/setprim_test.go index df71de74..f9a50e3d 100644 --- a/pkg/siftool/setprim_test.go +++ b/pkg/siftool/setprim_test.go @@ -2,7 +2,7 @@ // Apptainer a Series of LF Projects LLC. // For website terms of use, trademark policy, privacy policy and other // project policies see https://lfprojects.org/policies -// Copyright (c) 2021, Sylabs Inc. All rights reserved. +// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. // This software is licensed under a 3-clause BSD license. Please consult the // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. @@ -28,7 +28,7 @@ func Test_command_getSetPrim(t *testing.T) { cmd := c.getSetPrim() - runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}) + runCommand(t, cmd, []string{"1", makeTestSIF(t, true)}, nil) }) } } diff --git a/pkg/siftool/siftool_test.go b/pkg/siftool/siftool_test.go index ea8ca5a3..518b5c24 100644 --- a/pkg/siftool/siftool_test.go +++ b/pkg/siftool/siftool_test.go @@ -10,6 +10,7 @@ package siftool import ( "bytes" + "errors" "os" "path/filepath" "testing" @@ -51,7 +52,7 @@ func makeTestSIF(t *testing.T, withDataObject bool) string { return tf.Name() } -func runCommand(t *testing.T, cmd *cobra.Command, args []string) { +func runCommand(t *testing.T, cmd *cobra.Command, args []string, wantErr error) { t.Helper() var out, err bytes.Buffer @@ -60,8 +61,8 @@ func runCommand(t *testing.T, cmd *cobra.Command, args []string) { cmd.SetArgs(args) - if err := cmd.Execute(); err != nil { - t.Fatal(err) + if got, want := cmd.Execute(), wantErr; !errors.Is(got, want) { + t.Fatalf("got error %v, want %v", got, want) } g := goldie.New(t, @@ -135,7 +136,7 @@ func TestAddCommands(t *testing.T) { t.Fatal(err) } - runCommand(t, cmd, tt.args) + runCommand(t, cmd, tt.args, nil) }) } } diff --git a/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden b/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden new file mode 100644 index 00000000..cd860b84 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/Empty/err.golden @@ -0,0 +1 @@ +Error: failed to get partition descriptor: no objects in image diff --git a/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden b/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden new file mode 100644 index 00000000..f22522a8 --- /dev/null +++ b/pkg/siftool/testdata/Test_command_getMount/Empty/out.golden @@ -0,0 +1,9 @@ +Usage: + mount + +Examples: + mount image.sif path/ + +Flags: + -h, --help help for mount + diff --git a/pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden b/pkg/siftool/testdata/Test_command_getMount/OneGroup/err.golden new file mode 100644 index 00000000..e69de29b diff --git a/pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden b/pkg/siftool/testdata/Test_command_getMount/OneGroup/out.golden new file mode 100644 index 00000000..e69de29b From 0816623ae17fda75d8874aac3e9f1f2edf6a4c45 Mon Sep 17 00:00:00 2001 From: vlesich-sylabs Date: Wed, 6 Apr 2022 18:05:08 +0300 Subject: [PATCH 06/14] ci: update sbom format from spdx to cyclonedx Signed-off-by: Edita Kizinevic --- .goreleaser.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index f0f84886..3722a829 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -71,4 +71,7 @@ archives: - linux-builds sboms: - - artifacts: archive + - documents: + - "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.bom.cdx.json" + artifacts: binary + args: ["$artifact", "--file", "$document", "--output", "cyclonedx-json"] From acccc2970185517d7835443676f48412109f1a35 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 11 Apr 2022 15:43:19 +0000 Subject: [PATCH 07/14] build(deps): bump github.com/ProtonMail/go-crypto from v0.0.0-20220113124808-70ae35bab23f to v0.0.0-20220407094043-a94812496cf5 Signed-off-by: Edita Kizinevic --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a54c7997..be64dc06 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/apptainer/sif/v2 go 1.17 require ( - github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f + github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 github.com/blang/semver/v4 v4.0.0 github.com/go-git/go-git/v5 v5.4.2 github.com/google/uuid v1.3.0 diff --git a/go.sum b/go.sum index 55c96e7a..7df736c2 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f h1:J2FzIrXN82q5uyUraeJpLIm7U6PffRwje2ORho5yIik= -github.com/ProtonMail/go-crypto v0.0.0-20220113124808-70ae35bab23f/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= +github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5 h1:cSHEbLj0GZeHM1mWG84qEnGFojNEQ83W7cwaPRjcwXU= +github.com/ProtonMail/go-crypto v0.0.0-20220407094043-a94812496cf5/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= From b7c4a96e25e5cda1e7bff3bab16fb52d0e0a08aa Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 11 Apr 2022 16:50:30 +0000 Subject: [PATCH 08/14] ci: remove magefiles Remove magefiles and update CI config to use Go tooling natively. Signed-off-by: Edita Kizinevic --- .github/workflows/ci.yml | 4 +- .golangci.yml | 4 -- README.md | 19 +------ cmd/siftool/siftool.go | 7 +-- go.mod | 5 +- go.sum | 12 +--- magefiles/mage.go | 20 ------- magefiles/magefile.go | 119 --------------------------------------- 8 files changed, 11 insertions(+), 179 deletions(-) delete mode 100644 magefiles/mage.go delete mode 100644 magefiles/magefile.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46142d5b..c0482cf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: git diff --exit-code -- go.mod go.sum - name: Build Source - run: go run ./magefiles/mage.go build:source + run: go build ./... - name: Install Lint uses: golangci/golangci-lint-action@v2 @@ -44,7 +44,7 @@ jobs: golangci-lint run - name: Run Tests - run: go run ./magefiles/mage.go cover:unit cover.out + run: go test -coverprofile cover.out -race ./... - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.golangci.yml b/.golangci.yml index bc922c1e..5e9952b1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -2,10 +2,6 @@ # For website terms of use, trademark policy, privacy policy and other # project policies see https://lfprojects.org/policies -run: - build-tags: - - mage - linters: disable-all: true enable: diff --git a/README.md b/README.md index e5fb8b28..4d165032 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://github.com/apptainer/sif/actions/workflows/ci.yml/badge.svg)](https://github.com/apptainer/sif/actions/workflows/ci.yml) [![Code Coverage](https://codecov.io/gh/apptainer/sif/branch/master/graph/badge.svg)](https://codecov.io/gh/apptainer/sif) [![Go Report Card](https://goreportcard.com/badge/github.com/apptainer/sif)](https://goreportcard.com/report/github.com/apptainer/sif) -[![Built with Mage](https://magefile.org/badge.svg)](https://magefile.org) +[![Powered By GoReleaser](https://img.shields.io/badge/powered%20by-goreleaser-green.svg)](https://github.com/goreleaser) This module contains an open source implementation of the Singularity Image Format (SIF) that makes it easy to create complete and @@ -15,22 +15,9 @@ encapsulated container environments stored in a single file. Unless otherwise noted, the SIF source files are distributed under the BSD-style license found in the [LICENSE.md](LICENSE.md) file. -## Download and Install From Source +## Install Siftool -To get the sif package to use directly from your programs: - -```sh -go get -d github.com/apptainer/sif/v2 -``` - -To get the siftool CLI program installed to `$(go env GOPATH)/bin` to -manipulate SIF container files: - -```sh -git clone https://github.com/apptainer/sif -cd sif -go run ./magefiles/mage.go install -``` +Pre-built binaries are available with the [latest release](https://github.com/apptainer/sif/releases). ## Go Version Compatibility diff --git a/cmd/siftool/siftool.go b/cmd/siftool/siftool.go index 774bd545..2151417f 100644 --- a/cmd/siftool/siftool.go +++ b/cmd/siftool/siftool.go @@ -29,7 +29,6 @@ var ( date = "" builtBy = "" commit = "" - state = "" ) func writeVersion(w io.Writer) error { @@ -43,11 +42,7 @@ func writeVersion(w io.Writer) error { } if commit != "" { - if state == "" { - fmt.Fprintf(tw, "Commit:\t%v\n", commit) - } else { - fmt.Fprintf(tw, "Commit:\t%v (%v)\n", commit, state) - } + fmt.Fprintf(tw, "Commit:\t%v\n", commit) } if date != "" { diff --git a/go.mod b/go.mod index be64dc06..6c29fa86 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/blang/semver/v4 v4.0.0 github.com/go-git/go-git/v5 v5.4.2 github.com/google/uuid v1.3.0 - github.com/magefile/mage v1.13.0 github.com/sebdah/goldie/v2 v2.5.3 github.com/spf13/cobra v1.4.0 github.com/spf13/pflag v1.0.5 @@ -28,7 +27,7 @@ require ( github.com/sergi/go-diff v1.1.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect - golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect - golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect + golang.org/x/net v0.0.0-20210326060303-6b1517762897 // indirect + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 7df736c2..3a09e9a8 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magefile/mage v1.13.0 h1:XtLJl8bcCM7EFoO8FyH8XK3t7G5hQAeK+i4tq+veT9M= -github.com/magefile/mage v1.13.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -90,9 +88,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -100,16 +97,13 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/magefiles/mage.go b/magefiles/mage.go deleted file mode 100644 index a8104792..00000000 --- a/magefiles/mage.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Contributors to the Apptainer project, established as -// Apptainer a Series of LF Projects LLC. -// For website terms of use, trademark policy, privacy policy and other -// project policies see https://lfprojects.org/policies -// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. -// This software is licensed under a 3-clause BSD license. Please consult the -// LICENSE file distributed with the sources of this project regarding your -// rights to use or distribute this software. - -//go:build ignore - -package main - -import ( - "os" - - "github.com/magefile/mage/mage" -) - -func main() { os.Exit(mage.Main()) } diff --git a/magefiles/magefile.go b/magefiles/magefile.go deleted file mode 100644 index f2e8a605..00000000 --- a/magefiles/magefile.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) Contributors to the Apptainer project, established as -// Apptainer a Series of LF Projects LLC. -// For website terms of use, trademark policy, privacy policy and other -// project policies see https://lfprojects.org/policies -// Copyright (c) 2021-2022, Sylabs Inc. All rights reserved. -// This software is licensed under a 3-clause BSD license. Please consult the -// LICENSE file distributed with the sources of this project regarding your -// rights to use or distribute this software. - -//go:build mage - -package main - -import ( - "fmt" - "os" - "strings" - "time" - - "github.com/apptainer/sif/v2/internal/pkg/git" - "github.com/magefile/mage/mg" - "github.com/magefile/mage/sh" -) - -// Aliases defines command-line aliases exposed by Mage. -//nolint:deadcode -var Aliases = map[string]interface{}{ - "build": Build.All, - "cover": Cover.All, - "install": Install.All, - "test": Test.All, -} - -// env returns the environment to use when running Go commands. -func env() map[string]string { - return map[string]string{"CGO_ENABLED": "0"} -} - -// ldFlags returns linker flags to pass to various Go commands. -func ldFlags() string { - vals := []string{"-s", "-w", "-X", "main.builtBy=mage"} - - // Attempt to get git details. - if d, err := git.Describe("."); err == nil { - vals = append(vals, "-X", fmt.Sprintf("main.commit=%v", d.CommitHash())) - - if d.IsClean() { - vals = append(vals, - "-X", fmt.Sprintf("main.date=%v", d.CommitTime().UTC().Format(time.RFC3339)), - "-X", "main.state=clean", - ) - } else { - vals = append(vals, - "-X", fmt.Sprintf("main.date=%v", time.Now().UTC().Format(time.RFC3339)), - "-X", "main.state=dirty", - ) - } - - if v, err := d.Version(); err == nil { - vals = append(vals, "-X", fmt.Sprintf("main.version=%v", v)) - } else { - fmt.Fprintf(os.Stderr, "warning: failed to get version: %v\n", err) - } - } else { - fmt.Fprintf(os.Stderr, "warning: failed to describe git HEAD: %v\n", err) - - vals = append(vals, "-X", fmt.Sprintf("main.date=%v", time.Now().UTC().Format(time.RFC3339))) - } - - return strings.Join(vals, " ") -} - -type Build mg.Namespace - -// All compiles all assets. -func (ns Build) All() { - mg.Deps(ns.Source) -} - -// Source compiles all source code. -func (Build) Source() error { - return sh.RunWith(env(), mg.GoCmd(), "build", "-trimpath", "-ldflags", ldFlags(), "./...") -} - -type Install mg.Namespace - -// All installs all assets. -func (ns Install) All() { - mg.Deps(ns.Bin) -} - -// Bin installs binary to GOBIN. -func (Install) Bin() error { - return sh.RunWith(env(), mg.GoCmd(), "install", "-trimpath", "-ldflags", ldFlags(), "./cmd/siftool") -} - -type Test mg.Namespace - -// All runs all tests. -func (ns Test) All() { - mg.Deps(ns.Unit) -} - -// Unit runs all unit tests. -func (Test) Unit() error { - return sh.RunV(mg.GoCmd(), "test", "-race", "-cover", "./...") -} - -type Cover mg.Namespace - -// All runs all tests, writing coverage profile to the specified path. -func (ns Cover) All(path string) { - mg.Deps(mg.F(ns.Unit, path)) -} - -// Unit runs all unit tests, writing coverage profile to the specified path. -func (Cover) Unit(path string) error { - return sh.RunV(mg.GoCmd(), "test", "-race", "-coverprofile", path, "./...") -} From 97c1e2b9a473ed31aaa547d88ecb4b8abff94835 Mon Sep 17 00:00:00 2001 From: Edita Kizinevic Date: Tue, 10 May 2022 12:43:01 +0200 Subject: [PATCH 09/14] Update key Signed-off-by: Edita Kizinevic --- test/keys/private.asc | 71 ++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/test/keys/private.asc b/test/keys/private.asc index 0cb933ff..eddb82a7 100644 --- a/test/keys/private.asc +++ b/test/keys/private.asc @@ -1,4 +1,5 @@ -----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) lQOYBF6nUPABCACmd6vggtFfkZvYHJRv/u2UfazFL78oLhD05UpqEaS90ripzPN9 G30IF6WqxQHxia0nV/IqJ9Tjozs0nIaK761y69gCYbac27e1r6Pf4uCoTfOWeGVZ @@ -19,39 +20,39 @@ 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 -=zxMk +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 +=gDqC -----END PGP PRIVATE KEY BLOCK----- From d5a82b9aaaf7976978532526c662ca3d696f8623 Mon Sep 17 00:00:00 2001 From: vlesich-sylabs Date: Tue, 12 Apr 2022 19:37:16 +0300 Subject: [PATCH 10/14] ci: updated sbom name generating template Signed-off-by: Edita Kizinevic --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 3722a829..3ee14c5d 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -72,6 +72,6 @@ archives: sboms: - documents: - - "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.bom.cdx.json" + - '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}.bom.cdx.json' artifacts: binary args: ["$artifact", "--file", "$document", "--output", "cyclonedx-json"] From 13fd7ee2d79003fb7146d2f1079477ddfb6dd1ac Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 18 Apr 2022 08:57:47 -0500 Subject: [PATCH 11/14] mount: add option to specify squashfuse path Fixes sylabs/sif#204 Signed-off-by: Edita Kizinevic --- internal/pkg/exp/mount.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/internal/pkg/exp/mount.go b/internal/pkg/exp/mount.go index 8492cfb9..7c9d510f 100644 --- a/internal/pkg/exp/mount.go +++ b/internal/pkg/exp/mount.go @@ -30,8 +30,8 @@ func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo filepath.Clean(path), filepath.Clean(mountPath), } - - cmd := exec.CommandContext(ctx, "squashfuse", args...) + //nolint:gosec // note (gosec exclusion) - we require callers to be able to specify squashfuse not on PATH + cmd := exec.CommandContext(ctx, mo.squashfusePath, args...) cmd.Stdout = mo.stdout cmd.Stderr = mo.stderr @@ -44,8 +44,9 @@ func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo // mountOpts accumulates mount options. type mountOpts struct { - stdout io.Writer - stderr io.Writer + stdout io.Writer + stderr io.Writer + squashfusePath string } // MountOpt are used to specify mount options. @@ -67,6 +68,20 @@ func OptMountStderr(w io.Writer) MountOpt { } } +var errSquashfusePathInvalid = errors.New("squashfuse path must be relative or absolute") + +// OptMountSquashfusePath sets an explicit path to the squashfuse binary. The path must be an +// absolute or relative path. +func OptMountSquashfusePath(path string) MountOpt { + return func(mo *mountOpts) error { + if filepath.Base(path) == path { + return errSquashfusePathInvalid + } + mo.squashfusePath = path + return nil + } +} + var errUnsupportedFSType = errors.New("unrecognized filesystem type") // Mount mounts the primary system partition of the SIF file at path into mountPath. @@ -74,8 +89,13 @@ var errUnsupportedFSType = errors.New("unrecognized filesystem type") // Mount may start one or more underlying processes. By default, stdout and stderr of these // processes is discarded. To modify this behavior, consider using OptMountStdout and/or // OptMountStderr. +// +// By default, Mount searches for a squashfuse binary in the directories named by the PATH +// environment variable. To override this behavior, consider using OptMountSquashfusePath(). func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error { - mo := mountOpts{} + mo := mountOpts{ + squashfusePath: "squashfuse", + } for _, opt := range opts { if err := opt(&mo); err != nil { From 377a570f804b3512afc96a5b6c118cbecef175b4 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 18 Apr 2022 09:55:57 -0500 Subject: [PATCH 12/14] feat: Add experimental umount command Counterpart to mount, will unmount a squashfuse mounted filesystem via fusermount. Fixes sylabs/sif#205 Signed-off-by: Edita Kizinevic --- internal/app/siftool/unmount.go | 24 +++ internal/pkg/exp/unmount.go | 97 ++++++++++++ internal/pkg/exp/unmount_test.go | 143 ++++++++++++++++++ pkg/siftool/siftool.go | 1 + .../Test_command_getUnmount/err.golden | 0 .../Test_command_getUnmount/out.golden | 0 pkg/siftool/unmount.go | 31 ++++ pkg/siftool/unmount_test.go | 46 ++++++ 8 files changed, 342 insertions(+) create mode 100644 internal/app/siftool/unmount.go create mode 100644 internal/pkg/exp/unmount.go create mode 100644 internal/pkg/exp/unmount_test.go create mode 100644 pkg/siftool/testdata/Test_command_getUnmount/err.golden create mode 100644 pkg/siftool/testdata/Test_command_getUnmount/out.golden create mode 100644 pkg/siftool/unmount.go create mode 100644 pkg/siftool/unmount_test.go diff --git a/internal/app/siftool/unmount.go b/internal/app/siftool/unmount.go new file mode 100644 index 00000000..6986280b --- /dev/null +++ b/internal/app/siftool/unmount.go @@ -0,0 +1,24 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "context" + + "github.com/apptainer/sif/v2/internal/pkg/exp" +) + +// Unmounts the FUSE mounted filesystem at mountPath. +func (a *App) Unmount(ctx context.Context, mountPath string) error { + return exp.Unmount(ctx, mountPath, + exp.OptUnmountStdout(a.opts.out), + exp.OptUnmountStderr(a.opts.err), + ) +} diff --git a/internal/pkg/exp/unmount.go b/internal/pkg/exp/unmount.go new file mode 100644 index 00000000..a586bbe7 --- /dev/null +++ b/internal/pkg/exp/unmount.go @@ -0,0 +1,97 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package exp + +import ( + "context" + "errors" + "fmt" + "io" + "os/exec" + "path/filepath" +) + +// unmountSquashFS unmounts the filesystem at mountPath. +func unmountSquashFS(ctx context.Context, mountPath string, uo unmountOpts) error { + args := []string{ + "-u", + filepath.Clean(mountPath), + } + cmd := exec.CommandContext(ctx, uo.fusermountPath, args...) //nolint:gosec + cmd.Stdout = uo.stdout + cmd.Stderr = uo.stderr + + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to unmount: %w", err) + } + + return nil +} + +// unmountOpts accumulates unmount options. +type unmountOpts struct { + stdout io.Writer + stderr io.Writer + fusermountPath string +} + +// UnmountOpt are used to specify unmount options. +type UnmountOpt func(*unmountOpts) error + +// OptUnmountStdout writes standard output to w. +func OptUnmountStdout(w io.Writer) UnmountOpt { + return func(mo *unmountOpts) error { + mo.stdout = w + return nil + } +} + +// OptUnmountStderr writes standard error to w. +func OptUnmountStderr(w io.Writer) UnmountOpt { + return func(mo *unmountOpts) error { + mo.stderr = w + return nil + } +} + +var errFusermountPathInvalid = errors.New("fusermount path must be relative or absolute") + +// OptUnmountFusermountPath sets the path to the fusermount binary. +func OptUnmountFusermountPath(path string) UnmountOpt { + return func(mo *unmountOpts) error { + if filepath.Base(path) == path { + return errFusermountPathInvalid + } + mo.fusermountPath = path + return nil + } +} + +// Unmount the FUSE mounted filesystem at mountPath. +// +// Unmount may start one or more underlying processes. By default, stdout and stderr of these +// processes is discarded. To modify this behavior, consider using OptUnmountStdout and/or +// OptUnmountStderr. +// +// By default, Unmount searches for a fusermount binary in the directories named by the PATH +// environment variable. To override this behavior, consider using OptUnmountFusermountPath(). +func Unmount(ctx context.Context, mountPath string, opts ...UnmountOpt) error { + uo := unmountOpts{ + fusermountPath: "fusermount", + } + + for _, opt := range opts { + if err := opt(&uo); err != nil { + return fmt.Errorf("%w", err) + } + } + + return unmountSquashFS(ctx, mountPath, uo) +} diff --git a/internal/pkg/exp/unmount_test.go b/internal/pkg/exp/unmount_test.go new file mode 100644 index 00000000..9123df24 --- /dev/null +++ b/internal/pkg/exp/unmount_test.go @@ -0,0 +1,143 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package exp + +import ( + "bufio" + "context" + "errors" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +var corpus = filepath.Join("..", "..", "..", "test", "images") + +func Test_Unmount(t *testing.T) { + if _, err := exec.LookPath("squashfuse"); err != nil { + t.Skip(" not found, skipping mount tests") + } + fusermountPath, err := exec.LookPath("fusermount") + if err != nil { + t.Skip(" not found, skipping mount tests") + } + + path, err := os.MkdirTemp("", "siftool-mount-*") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + os.RemoveAll(path) + }) + + tests := []struct { + name string + mountSIF string + mountPath string + opts []UnmountOpt + wantErr bool + wantUnmounted bool + }{ + { + name: "Mounted", + mountSIF: filepath.Join(corpus, "one-group.sif"), + mountPath: path, + wantErr: false, + wantUnmounted: true, + }, + { + name: "NotMounted", + mountSIF: "", + mountPath: path, + wantErr: true, + }, + { + name: "NotSquashfuse", + mountSIF: "", + mountPath: "/dev", + wantErr: true, + }, + { + name: "FusermountBare", + mountSIF: "", + mountPath: path, + opts: []UnmountOpt{OptUnmountFusermountPath("fusermount")}, + wantErr: true, + }, + { + name: "FusermountValid", + mountSIF: filepath.Join(corpus, "one-group.sif"), + mountPath: path, + opts: []UnmountOpt{OptUnmountFusermountPath(fusermountPath)}, + wantErr: false, + wantUnmounted: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.mountSIF != "" { + err := Mount(context.Background(), tt.mountSIF, path) + if err != nil { + t.Fatal(err) + } + } + + err := Unmount(context.Background(), tt.mountPath, tt.opts...) + + if err != nil && !tt.wantErr { + t.Errorf("Unexpected error: %s", err) + } + if err == nil && tt.wantErr { + t.Error("Unexpected success") + } + + mounted, err := isMounted(tt.mountPath) + if err != nil { + t.Fatal(err) + } + if tt.wantUnmounted && mounted { + t.Errorf("Expected %s to be unmounted, but it is mounted", tt.mountPath) + } + }) + } +} + +var errBadMountInfo = errors.New("bad mount info") + +func isMounted(mountPath string) (bool, error) { + mountPath, err := filepath.Abs(mountPath) + if err != nil { + return false, err + } + + mi, err := os.Open("/proc/self/mountinfo") + if err != nil { + return false, fmt.Errorf("failed to open /proc/self/mountinfo: %w", err) + } + defer mi.Close() + + scanner := bufio.NewScanner(mi) + for scanner.Scan() { + fields := strings.Split(scanner.Text(), " ") + if len(fields) < 5 { + return false, fmt.Errorf("not enough mountinfo fields: %w", errBadMountInfo) + } + //nolint:lll + // 1348 63 0:77 / /tmp/siftool-mount-956028386 ro,nosuid,nodev,relatime shared:646 - fuse.squashfuse squashfuse ro,user_id=1000,group_id=100 + mntTarget := fields[4] + if mntTarget == mountPath { + return true, nil + } + } + return false, nil +} diff --git a/pkg/siftool/siftool.go b/pkg/siftool/siftool.go index 50ac8f20..464875cd 100644 --- a/pkg/siftool/siftool.go +++ b/pkg/siftool/siftool.go @@ -82,6 +82,7 @@ func AddCommands(cmd *cobra.Command, opts ...CommandOpt) error { if c.opts.experimental { cmd.AddCommand(c.getMount()) + cmd.AddCommand(c.getUnmount()) } return nil diff --git a/pkg/siftool/testdata/Test_command_getUnmount/err.golden b/pkg/siftool/testdata/Test_command_getUnmount/err.golden new file mode 100644 index 00000000..e69de29b diff --git a/pkg/siftool/testdata/Test_command_getUnmount/out.golden b/pkg/siftool/testdata/Test_command_getUnmount/out.golden new file mode 100644 index 00000000..e69de29b diff --git a/pkg/siftool/unmount.go b/pkg/siftool/unmount.go new file mode 100644 index 00000000..fdb7c259 --- /dev/null +++ b/pkg/siftool/unmount.go @@ -0,0 +1,31 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "github.com/spf13/cobra" +) + +// getUnmount returns a command that unmounts the primary system partition of a SIF image. +func (c *command) getUnmount() *cobra.Command { + return &cobra.Command{ + Use: "unmount ", + Short: "Unmount primary system partition", + Long: "Unmount a primary system partition of a SIF image", + Example: c.opts.rootPath + " unmount path/", + Args: cobra.ExactArgs(1), + PreRunE: c.initApp, + RunE: func(cmd *cobra.Command, args []string) error { + return c.app.Unmount(cmd.Context(), args[0]) + }, + DisableFlagsInUseLine: true, + Hidden: true, // hide while command is experimental + } +} diff --git a/pkg/siftool/unmount_test.go b/pkg/siftool/unmount_test.go new file mode 100644 index 00000000..eef54b8b --- /dev/null +++ b/pkg/siftool/unmount_test.go @@ -0,0 +1,46 @@ +// Copyright (c) Contributors to the Apptainer project, established as +// Apptainer a Series of LF Projects LLC. +// For website terms of use, trademark policy, privacy policy and other +// project policies see https://lfprojects.org/policies +// Copyright (c) 2022, Sylabs Inc. All rights reserved. +// This software is licensed under a 3-clause BSD license. Please consult the +// LICENSE file distributed with the sources of this project regarding your +// rights to use or distribute this software. + +package siftool + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/apptainer/sif/v2/internal/pkg/exp" +) + +func Test_command_getUnmount(t *testing.T) { + if _, err := exec.LookPath("squashfuse"); err != nil { + t.Skip(" not found, skipping unmount tests") + } + if _, err := exec.LookPath("fusermount"); err != nil { + t.Skip(" not found, skipping unmount tests") + } + + path, err := os.MkdirTemp("", "siftool-unmount-*") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + os.RemoveAll(path) + }) + + testSIF := filepath.Join(corpus, "one-group.sif") + if err := exp.Mount(context.Background(), testSIF, path); err != nil { + t.Fatal(err) + } + + c := &command{} + cmd := c.getUnmount() + runCommand(t, cmd, []string{path}, nil) +} From a9cf1d2012f63f62f2007b762b26afe1d3b225f7 Mon Sep 17 00:00:00 2001 From: David Trudgian Date: Mon, 18 Apr 2022 09:55:57 -0500 Subject: [PATCH 13/14] feat: expose MountFUSE / UnmountFUSE API Move `Mount` and `Unmount` to `pkg` from `internal`. Rename to `xxxxFUSE` to make it clear these are FUSE mounts, rather than anything else. Fixes sylabs/sif#206 Signed-off-by: Edita Kizinevic --- internal/app/siftool/mount.go | 8 ++-- internal/app/siftool/unmount.go | 8 ++-- {internal/pkg/exp => pkg/sif}/mount.go | 48 +++++++++---------- {internal/pkg/exp => pkg/sif}/unmount.go | 40 ++++++++-------- {internal/pkg/exp => pkg/sif}/unmount_test.go | 16 +++---- pkg/siftool/unmount_test.go | 4 +- 6 files changed, 59 insertions(+), 65 deletions(-) rename {internal/pkg/exp => pkg/sif}/mount.go (65%) rename {internal/pkg/exp => pkg/sif}/unmount.go (62%) rename {internal/pkg/exp => pkg/sif}/unmount_test.go (88%) diff --git a/internal/app/siftool/mount.go b/internal/app/siftool/mount.go index d5fb7dba..f3cd9c23 100644 --- a/internal/app/siftool/mount.go +++ b/internal/app/siftool/mount.go @@ -12,13 +12,13 @@ package siftool import ( "context" - "github.com/apptainer/sif/v2/internal/pkg/exp" + "github.com/apptainer/sif/v2/pkg/sif" ) // Mount mounts the primary system partition of the SIF file at path into mountPath. func (a *App) Mount(ctx context.Context, path, mountPath string) error { - return exp.Mount(ctx, path, mountPath, - exp.OptMountStdout(a.opts.out), - exp.OptMountStderr(a.opts.err), + return sif.MountFUSE(ctx, path, mountPath, + sif.OptMountFUSEStdout(a.opts.out), + sif.OptMountFUSEStderr(a.opts.err), ) } diff --git a/internal/app/siftool/unmount.go b/internal/app/siftool/unmount.go index 6986280b..86d1ef99 100644 --- a/internal/app/siftool/unmount.go +++ b/internal/app/siftool/unmount.go @@ -12,13 +12,13 @@ package siftool import ( "context" - "github.com/apptainer/sif/v2/internal/pkg/exp" + "github.com/apptainer/sif/v2/pkg/sif" ) // Unmounts the FUSE mounted filesystem at mountPath. func (a *App) Unmount(ctx context.Context, mountPath string) error { - return exp.Unmount(ctx, mountPath, - exp.OptUnmountStdout(a.opts.out), - exp.OptUnmountStderr(a.opts.err), + return sif.UnmountFUSE(ctx, mountPath, + sif.OptUnmountFUSEStdout(a.opts.out), + sif.OptUnmountFUSEStderr(a.opts.err), ) } diff --git a/internal/pkg/exp/mount.go b/pkg/sif/mount.go similarity index 65% rename from internal/pkg/exp/mount.go rename to pkg/sif/mount.go index 7c9d510f..7c5457fa 100644 --- a/internal/pkg/exp/mount.go +++ b/pkg/sif/mount.go @@ -7,9 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -// Package exp contains experimental functionality that is not sufficiently mature to be exported -// as part of the module API. -package exp +package sif import ( "context" @@ -19,12 +17,10 @@ import ( "os" "os/exec" "path/filepath" - - "github.com/apptainer/sif/v2/pkg/sif" ) // mountSquashFS mounts the SquashFS filesystem from path at offset into mountPath. -func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountOpts) error { +func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountFUSEOpts) error { args := []string{ "-o", fmt.Sprintf("ro,offset=%d", offset), filepath.Clean(path), @@ -42,27 +38,27 @@ func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo return nil } -// mountOpts accumulates mount options. -type mountOpts struct { +// mountFUSEOpts accumulates mount options. +type mountFUSEOpts struct { stdout io.Writer stderr io.Writer squashfusePath string } -// MountOpt are used to specify mount options. -type MountOpt func(*mountOpts) error +// MountFUSEOpt are used to specify mount options. +type MountFUSEOpt func(*mountFUSEOpts) error // OptMountStdout writes standard output to w. -func OptMountStdout(w io.Writer) MountOpt { - return func(mo *mountOpts) error { +func OptMountFUSEStdout(w io.Writer) MountFUSEOpt { + return func(mo *mountFUSEOpts) error { mo.stdout = w return nil } } -// OptMountStderr writes standard error to w. -func OptMountStderr(w io.Writer) MountOpt { - return func(mo *mountOpts) error { +// OptMountFUSEStderr writes standard error to w. +func OptMountFUSEStderr(w io.Writer) MountFUSEOpt { + return func(mo *mountFUSEOpts) error { mo.stderr = w return nil } @@ -70,10 +66,10 @@ func OptMountStderr(w io.Writer) MountOpt { var errSquashfusePathInvalid = errors.New("squashfuse path must be relative or absolute") -// OptMountSquashfusePath sets an explicit path to the squashfuse binary. The path must be an +// OptMountFUSESquashfusePath sets an explicit path to the squashfuse binary. The path must be an // absolute or relative path. -func OptMountSquashfusePath(path string) MountOpt { - return func(mo *mountOpts) error { +func OptMountFUSESquashfusePath(path string) MountFUSEOpt { + return func(mo *mountFUSEOpts) error { if filepath.Base(path) == path { return errSquashfusePathInvalid } @@ -84,16 +80,16 @@ func OptMountSquashfusePath(path string) MountOpt { var errUnsupportedFSType = errors.New("unrecognized filesystem type") -// Mount mounts the primary system partition of the SIF file at path into mountPath. +// MountFUSE mounts the primary system partition of the SIF file at path into mountPath. // -// Mount may start one or more underlying processes. By default, stdout and stderr of these +// MountFUSE may start one or more underlying processes. By default, stdout and stderr of these // processes is discarded. To modify this behavior, consider using OptMountStdout and/or // OptMountStderr. // -// By default, Mount searches for a squashfuse binary in the directories named by the PATH +// By default, MountFUSE searches for a squashfuse binary in the directories named by the PATH // environment variable. To override this behavior, consider using OptMountSquashfusePath(). -func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error { - mo := mountOpts{ +func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt) error { + mo := mountFUSEOpts{ squashfusePath: "squashfuse", } @@ -103,13 +99,13 @@ func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error } } - f, err := sif.LoadContainerFromPath(path, sif.OptLoadWithFlag(os.O_RDONLY)) + f, err := LoadContainerFromPath(path, OptLoadWithFlag(os.O_RDONLY)) if err != nil { return fmt.Errorf("failed to load image: %w", err) } defer func() { _ = f.UnloadContainer() }() - d, err := f.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys)) + d, err := f.GetDescriptor(WithPartitionType(PartPrimSys)) if err != nil { return fmt.Errorf("failed to get partition descriptor: %w", err) } @@ -120,7 +116,7 @@ func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error } switch fs { - case sif.FsSquash: + case FsSquash: return mountSquashFS(ctx, d.Offset(), path, mountPath, mo) default: return errUnsupportedFSType diff --git a/internal/pkg/exp/unmount.go b/pkg/sif/unmount.go similarity index 62% rename from internal/pkg/exp/unmount.go rename to pkg/sif/unmount.go index a586bbe7..4531b90a 100644 --- a/internal/pkg/exp/unmount.go +++ b/pkg/sif/unmount.go @@ -7,7 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -package exp +package sif import ( "context" @@ -19,7 +19,7 @@ import ( ) // unmountSquashFS unmounts the filesystem at mountPath. -func unmountSquashFS(ctx context.Context, mountPath string, uo unmountOpts) error { +func unmountSquashFS(ctx context.Context, mountPath string, uo unmountFUSEOpts) error { args := []string{ "-u", filepath.Clean(mountPath), @@ -35,27 +35,27 @@ func unmountSquashFS(ctx context.Context, mountPath string, uo unmountOpts) erro return nil } -// unmountOpts accumulates unmount options. -type unmountOpts struct { +// unmountFUSEOpts accumulates unmount options. +type unmountFUSEOpts struct { stdout io.Writer stderr io.Writer fusermountPath string } -// UnmountOpt are used to specify unmount options. -type UnmountOpt func(*unmountOpts) error +// UnmountFUSEOpt are used to specify unmount options. +type UnmountFUSEOpt func(*unmountFUSEOpts) error -// OptUnmountStdout writes standard output to w. -func OptUnmountStdout(w io.Writer) UnmountOpt { - return func(mo *unmountOpts) error { +// OptUnmountFUSEStdout writes standard output to w. +func OptUnmountFUSEStdout(w io.Writer) UnmountFUSEOpt { + return func(mo *unmountFUSEOpts) error { mo.stdout = w return nil } } -// OptUnmountStderr writes standard error to w. -func OptUnmountStderr(w io.Writer) UnmountOpt { - return func(mo *unmountOpts) error { +// OptUnmountFUSEStderr writes standard error to w. +func OptUnmountFUSEStderr(w io.Writer) UnmountFUSEOpt { + return func(mo *unmountFUSEOpts) error { mo.stderr = w return nil } @@ -63,9 +63,9 @@ func OptUnmountStderr(w io.Writer) UnmountOpt { var errFusermountPathInvalid = errors.New("fusermount path must be relative or absolute") -// OptUnmountFusermountPath sets the path to the fusermount binary. -func OptUnmountFusermountPath(path string) UnmountOpt { - return func(mo *unmountOpts) error { +// OptUnmountFUSEFusermountPath sets the path to the fusermount binary. +func OptUnmountFUSEFusermountPath(path string) UnmountFUSEOpt { + return func(mo *unmountFUSEOpts) error { if filepath.Base(path) == path { return errFusermountPathInvalid } @@ -74,16 +74,16 @@ func OptUnmountFusermountPath(path string) UnmountOpt { } } -// Unmount the FUSE mounted filesystem at mountPath. +// UnmountFUSE unmounts the FUSE mounted filesystem at mountPath. // -// Unmount may start one or more underlying processes. By default, stdout and stderr of these +// UnmountFUSE may start one or more underlying processes. By default, stdout and stderr of these // processes is discarded. To modify this behavior, consider using OptUnmountStdout and/or // OptUnmountStderr. // -// By default, Unmount searches for a fusermount binary in the directories named by the PATH +// By default, UnmountFUSE searches for a fusermount binary in the directories named by the PATH // environment variable. To override this behavior, consider using OptUnmountFusermountPath(). -func Unmount(ctx context.Context, mountPath string, opts ...UnmountOpt) error { - uo := unmountOpts{ +func UnmountFUSE(ctx context.Context, mountPath string, opts ...UnmountFUSEOpt) error { + uo := unmountFUSEOpts{ fusermountPath: "fusermount", } diff --git a/internal/pkg/exp/unmount_test.go b/pkg/sif/unmount_test.go similarity index 88% rename from internal/pkg/exp/unmount_test.go rename to pkg/sif/unmount_test.go index 9123df24..002c13e9 100644 --- a/internal/pkg/exp/unmount_test.go +++ b/pkg/sif/unmount_test.go @@ -7,7 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -package exp +package sif import ( "bufio" @@ -21,9 +21,7 @@ import ( "testing" ) -var corpus = filepath.Join("..", "..", "..", "test", "images") - -func Test_Unmount(t *testing.T) { +func Test_UnmountFUSE(t *testing.T) { if _, err := exec.LookPath("squashfuse"); err != nil { t.Skip(" not found, skipping mount tests") } @@ -44,7 +42,7 @@ func Test_Unmount(t *testing.T) { name string mountSIF string mountPath string - opts []UnmountOpt + opts []UnmountFUSEOpt wantErr bool wantUnmounted bool }{ @@ -71,14 +69,14 @@ func Test_Unmount(t *testing.T) { name: "FusermountBare", mountSIF: "", mountPath: path, - opts: []UnmountOpt{OptUnmountFusermountPath("fusermount")}, + opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath("fusermount")}, wantErr: true, }, { name: "FusermountValid", mountSIF: filepath.Join(corpus, "one-group.sif"), mountPath: path, - opts: []UnmountOpt{OptUnmountFusermountPath(fusermountPath)}, + opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath(fusermountPath)}, wantErr: false, wantUnmounted: true, }, @@ -86,13 +84,13 @@ func Test_Unmount(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.mountSIF != "" { - err := Mount(context.Background(), tt.mountSIF, path) + err := MountFUSE(context.Background(), tt.mountSIF, path) if err != nil { t.Fatal(err) } } - err := Unmount(context.Background(), tt.mountPath, tt.opts...) + err := UnmountFUSE(context.Background(), tt.mountPath, tt.opts...) if err != nil && !tt.wantErr { t.Errorf("Unexpected error: %s", err) diff --git a/pkg/siftool/unmount_test.go b/pkg/siftool/unmount_test.go index eef54b8b..676656b8 100644 --- a/pkg/siftool/unmount_test.go +++ b/pkg/siftool/unmount_test.go @@ -16,7 +16,7 @@ import ( "path/filepath" "testing" - "github.com/apptainer/sif/v2/internal/pkg/exp" + "github.com/apptainer/sif/v2/pkg/sif" ) func Test_command_getUnmount(t *testing.T) { @@ -36,7 +36,7 @@ func Test_command_getUnmount(t *testing.T) { }) testSIF := filepath.Join(corpus, "one-group.sif") - if err := exp.Mount(context.Background(), testSIF, path); err != nil { + if err := sif.MountFUSE(context.Background(), testSIF, path); err != nil { t.Fatal(err) } From 42e4c74b53993f266bdd747cecfbf75d517303e0 Mon Sep 17 00:00:00 2001 From: Adam Hughes Date: Mon, 25 Apr 2022 14:55:35 +0000 Subject: [PATCH 14/14] refactor: move mount/unmount to user package Signed-off-by: Edita Kizinevic --- internal/app/siftool/mount.go | 8 +++--- internal/app/siftool/unmount.go | 10 +++---- pkg/siftool/unmount_test.go | 4 +-- pkg/{sif => user}/mount.go | 46 ++++++++++++++++--------------- pkg/{sif => user}/unmount.go | 40 +++++++++++++-------------- pkg/{sif => user}/unmount_test.go | 16 ++++++----- 6 files changed, 64 insertions(+), 60 deletions(-) rename pkg/{sif => user}/mount.go (67%) rename pkg/{sif => user}/unmount.go (62%) rename pkg/{sif => user}/unmount_test.go (88%) diff --git a/internal/app/siftool/mount.go b/internal/app/siftool/mount.go index f3cd9c23..1287c61c 100644 --- a/internal/app/siftool/mount.go +++ b/internal/app/siftool/mount.go @@ -12,13 +12,13 @@ package siftool import ( "context" - "github.com/apptainer/sif/v2/pkg/sif" + "github.com/apptainer/sif/v2/pkg/user" ) // Mount mounts the primary system partition of the SIF file at path into mountPath. func (a *App) Mount(ctx context.Context, path, mountPath string) error { - return sif.MountFUSE(ctx, path, mountPath, - sif.OptMountFUSEStdout(a.opts.out), - sif.OptMountFUSEStderr(a.opts.err), + return user.Mount(ctx, path, mountPath, + user.OptMountStdout(a.opts.out), + user.OptMountStderr(a.opts.err), ) } diff --git a/internal/app/siftool/unmount.go b/internal/app/siftool/unmount.go index 86d1ef99..915df3f9 100644 --- a/internal/app/siftool/unmount.go +++ b/internal/app/siftool/unmount.go @@ -12,13 +12,13 @@ package siftool import ( "context" - "github.com/apptainer/sif/v2/pkg/sif" + "github.com/apptainer/sif/v2/pkg/user" ) -// Unmounts the FUSE mounted filesystem at mountPath. +// Unmounts the filesystem at mountPath. func (a *App) Unmount(ctx context.Context, mountPath string) error { - return sif.UnmountFUSE(ctx, mountPath, - sif.OptUnmountFUSEStdout(a.opts.out), - sif.OptUnmountFUSEStderr(a.opts.err), + return user.Unmount(ctx, mountPath, + user.OptUnmountStdout(a.opts.out), + user.OptUnmountStderr(a.opts.err), ) } diff --git a/pkg/siftool/unmount_test.go b/pkg/siftool/unmount_test.go index 676656b8..1cfd2656 100644 --- a/pkg/siftool/unmount_test.go +++ b/pkg/siftool/unmount_test.go @@ -16,7 +16,7 @@ import ( "path/filepath" "testing" - "github.com/apptainer/sif/v2/pkg/sif" + "github.com/apptainer/sif/v2/pkg/user" ) func Test_command_getUnmount(t *testing.T) { @@ -36,7 +36,7 @@ func Test_command_getUnmount(t *testing.T) { }) testSIF := filepath.Join(corpus, "one-group.sif") - if err := sif.MountFUSE(context.Background(), testSIF, path); err != nil { + if err := user.Mount(context.Background(), testSIF, path); err != nil { t.Fatal(err) } diff --git a/pkg/sif/mount.go b/pkg/user/mount.go similarity index 67% rename from pkg/sif/mount.go rename to pkg/user/mount.go index 7c5457fa..9283773c 100644 --- a/pkg/sif/mount.go +++ b/pkg/user/mount.go @@ -7,7 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -package sif +package user import ( "context" @@ -17,10 +17,12 @@ import ( "os" "os/exec" "path/filepath" + + "github.com/apptainer/sif/v2/pkg/sif" ) // mountSquashFS mounts the SquashFS filesystem from path at offset into mountPath. -func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountFUSEOpts) error { +func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo mountOpts) error { args := []string{ "-o", fmt.Sprintf("ro,offset=%d", offset), filepath.Clean(path), @@ -38,27 +40,27 @@ func mountSquashFS(ctx context.Context, offset int64, path, mountPath string, mo return nil } -// mountFUSEOpts accumulates mount options. -type mountFUSEOpts struct { +// mountOpts accumulates mount options. +type mountOpts struct { stdout io.Writer stderr io.Writer squashfusePath string } -// MountFUSEOpt are used to specify mount options. -type MountFUSEOpt func(*mountFUSEOpts) error +// MountOpt are used to specify mount options. +type MountOpt func(*mountOpts) error // OptMountStdout writes standard output to w. -func OptMountFUSEStdout(w io.Writer) MountFUSEOpt { - return func(mo *mountFUSEOpts) error { +func OptMountStdout(w io.Writer) MountOpt { + return func(mo *mountOpts) error { mo.stdout = w return nil } } -// OptMountFUSEStderr writes standard error to w. -func OptMountFUSEStderr(w io.Writer) MountFUSEOpt { - return func(mo *mountFUSEOpts) error { +// OptMountStderr writes standard error to w. +func OptMountStderr(w io.Writer) MountOpt { + return func(mo *mountOpts) error { mo.stderr = w return nil } @@ -66,10 +68,10 @@ func OptMountFUSEStderr(w io.Writer) MountFUSEOpt { var errSquashfusePathInvalid = errors.New("squashfuse path must be relative or absolute") -// OptMountFUSESquashfusePath sets an explicit path to the squashfuse binary. The path must be an +// OptMountSquashfusePath sets an explicit path to the squashfuse binary. The path must be an // absolute or relative path. -func OptMountFUSESquashfusePath(path string) MountFUSEOpt { - return func(mo *mountFUSEOpts) error { +func OptMountSquashfusePath(path string) MountOpt { + return func(mo *mountOpts) error { if filepath.Base(path) == path { return errSquashfusePathInvalid } @@ -80,16 +82,16 @@ func OptMountFUSESquashfusePath(path string) MountFUSEOpt { var errUnsupportedFSType = errors.New("unrecognized filesystem type") -// MountFUSE mounts the primary system partition of the SIF file at path into mountPath. +// Mount mounts the primary system partition of the SIF file at path into mountPath. // -// MountFUSE may start one or more underlying processes. By default, stdout and stderr of these +// Mount may start one or more underlying processes. By default, stdout and stderr of these // processes is discarded. To modify this behavior, consider using OptMountStdout and/or // OptMountStderr. // -// By default, MountFUSE searches for a squashfuse binary in the directories named by the PATH +// By default, Mount searches for a squashfuse binary in the directories named by the PATH // environment variable. To override this behavior, consider using OptMountSquashfusePath(). -func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt) error { - mo := mountFUSEOpts{ +func Mount(ctx context.Context, path, mountPath string, opts ...MountOpt) error { + mo := mountOpts{ squashfusePath: "squashfuse", } @@ -99,13 +101,13 @@ func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt } } - f, err := LoadContainerFromPath(path, OptLoadWithFlag(os.O_RDONLY)) + f, err := sif.LoadContainerFromPath(path, sif.OptLoadWithFlag(os.O_RDONLY)) if err != nil { return fmt.Errorf("failed to load image: %w", err) } defer func() { _ = f.UnloadContainer() }() - d, err := f.GetDescriptor(WithPartitionType(PartPrimSys)) + d, err := f.GetDescriptor(sif.WithPartitionType(sif.PartPrimSys)) if err != nil { return fmt.Errorf("failed to get partition descriptor: %w", err) } @@ -116,7 +118,7 @@ func MountFUSE(ctx context.Context, path, mountPath string, opts ...MountFUSEOpt } switch fs { - case FsSquash: + case sif.FsSquash: return mountSquashFS(ctx, d.Offset(), path, mountPath, mo) default: return errUnsupportedFSType diff --git a/pkg/sif/unmount.go b/pkg/user/unmount.go similarity index 62% rename from pkg/sif/unmount.go rename to pkg/user/unmount.go index 4531b90a..4c48f79c 100644 --- a/pkg/sif/unmount.go +++ b/pkg/user/unmount.go @@ -7,7 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -package sif +package user import ( "context" @@ -19,7 +19,7 @@ import ( ) // unmountSquashFS unmounts the filesystem at mountPath. -func unmountSquashFS(ctx context.Context, mountPath string, uo unmountFUSEOpts) error { +func unmountSquashFS(ctx context.Context, mountPath string, uo unmountOpts) error { args := []string{ "-u", filepath.Clean(mountPath), @@ -35,27 +35,27 @@ func unmountSquashFS(ctx context.Context, mountPath string, uo unmountFUSEOpts) return nil } -// unmountFUSEOpts accumulates unmount options. -type unmountFUSEOpts struct { +// unmountOpts accumulates unmount options. +type unmountOpts struct { stdout io.Writer stderr io.Writer fusermountPath string } -// UnmountFUSEOpt are used to specify unmount options. -type UnmountFUSEOpt func(*unmountFUSEOpts) error +// UnmountOpt are used to specify unmount options. +type UnmountOpt func(*unmountOpts) error -// OptUnmountFUSEStdout writes standard output to w. -func OptUnmountFUSEStdout(w io.Writer) UnmountFUSEOpt { - return func(mo *unmountFUSEOpts) error { +// OptUnmountStdout writes standard output to w. +func OptUnmountStdout(w io.Writer) UnmountOpt { + return func(mo *unmountOpts) error { mo.stdout = w return nil } } -// OptUnmountFUSEStderr writes standard error to w. -func OptUnmountFUSEStderr(w io.Writer) UnmountFUSEOpt { - return func(mo *unmountFUSEOpts) error { +// OptUnmountStderr writes standard error to w. +func OptUnmountStderr(w io.Writer) UnmountOpt { + return func(mo *unmountOpts) error { mo.stderr = w return nil } @@ -63,9 +63,9 @@ func OptUnmountFUSEStderr(w io.Writer) UnmountFUSEOpt { var errFusermountPathInvalid = errors.New("fusermount path must be relative or absolute") -// OptUnmountFUSEFusermountPath sets the path to the fusermount binary. -func OptUnmountFUSEFusermountPath(path string) UnmountFUSEOpt { - return func(mo *unmountFUSEOpts) error { +// OptUnmountFusermountPath sets the path to the fusermount binary. +func OptUnmountFusermountPath(path string) UnmountOpt { + return func(mo *unmountOpts) error { if filepath.Base(path) == path { return errFusermountPathInvalid } @@ -74,16 +74,16 @@ func OptUnmountFUSEFusermountPath(path string) UnmountFUSEOpt { } } -// UnmountFUSE unmounts the FUSE mounted filesystem at mountPath. +// Unmount unmounts the filesystem at mountPath. // -// UnmountFUSE may start one or more underlying processes. By default, stdout and stderr of these +// Unmount may start one or more underlying processes. By default, stdout and stderr of these // processes is discarded. To modify this behavior, consider using OptUnmountStdout and/or // OptUnmountStderr. // -// By default, UnmountFUSE searches for a fusermount binary in the directories named by the PATH +// By default, Unmount searches for a fusermount binary in the directories named by the PATH // environment variable. To override this behavior, consider using OptUnmountFusermountPath(). -func UnmountFUSE(ctx context.Context, mountPath string, opts ...UnmountFUSEOpt) error { - uo := unmountFUSEOpts{ +func Unmount(ctx context.Context, mountPath string, opts ...UnmountOpt) error { + uo := unmountOpts{ fusermountPath: "fusermount", } diff --git a/pkg/sif/unmount_test.go b/pkg/user/unmount_test.go similarity index 88% rename from pkg/sif/unmount_test.go rename to pkg/user/unmount_test.go index 002c13e9..aea98658 100644 --- a/pkg/sif/unmount_test.go +++ b/pkg/user/unmount_test.go @@ -7,7 +7,7 @@ // LICENSE file distributed with the sources of this project regarding your // rights to use or distribute this software. -package sif +package user import ( "bufio" @@ -21,7 +21,9 @@ import ( "testing" ) -func Test_UnmountFUSE(t *testing.T) { +var corpus = filepath.Join("..", "..", "test", "images") + +func Test_Unmount(t *testing.T) { if _, err := exec.LookPath("squashfuse"); err != nil { t.Skip(" not found, skipping mount tests") } @@ -42,7 +44,7 @@ func Test_UnmountFUSE(t *testing.T) { name string mountSIF string mountPath string - opts []UnmountFUSEOpt + opts []UnmountOpt wantErr bool wantUnmounted bool }{ @@ -69,14 +71,14 @@ func Test_UnmountFUSE(t *testing.T) { name: "FusermountBare", mountSIF: "", mountPath: path, - opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath("fusermount")}, + opts: []UnmountOpt{OptUnmountFusermountPath("fusermount")}, wantErr: true, }, { name: "FusermountValid", mountSIF: filepath.Join(corpus, "one-group.sif"), mountPath: path, - opts: []UnmountFUSEOpt{OptUnmountFUSEFusermountPath(fusermountPath)}, + opts: []UnmountOpt{OptUnmountFusermountPath(fusermountPath)}, wantErr: false, wantUnmounted: true, }, @@ -84,13 +86,13 @@ func Test_UnmountFUSE(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.mountSIF != "" { - err := MountFUSE(context.Background(), tt.mountSIF, path) + err := Mount(context.Background(), tt.mountSIF, path) if err != nil { t.Fatal(err) } } - err := UnmountFUSE(context.Background(), tt.mountPath, tt.opts...) + err := Unmount(context.Background(), tt.mountPath, tt.opts...) if err != nil && !tt.wantErr { t.Errorf("Unexpected error: %s", err)