diff --git a/common/playbooks/files/egi-binder-logo.svg b/common/playbooks/files/egi-binder-logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..be13a98b3357810d5c3aec7a562f2542126bde08 --- /dev/null +++ b/common/playbooks/files/egi-binder-logo.svg @@ -0,0 +1,312 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="133.18167mm" + height="23.136333mm" + viewBox="0 0 133.18167 23.136333" + version="1.1" + id="svg1206" + inkscape:version="1.1.1 (c3084ef, 2021-09-22)" + sodipodi:docname="egi-binder-logo.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + <sodipodi:namedview + id="namedview1208" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="mm" + showgrid="false" + inkscape:zoom="0.64052329" + inkscape:cx="-100.69891" + inkscape:cy="174.07642" + inkscape:window-width="1312" + inkscape:window-height="969" + inkscape:window-x="760" + inkscape:window-y="320" + inkscape:window-maximized="0" + inkscape:current-layer="layer1" /> + <defs + id="defs1203" /> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-51.886497,-82.320502)"> + <g + id="g690" + transform="matrix(0.1160515,0,0,0.1160515,47.950486,79.544877)"> + <path + fill="#999999" + d="m 165.04,37.83 c 0.699,-5.219 5.16,-9.017 10.293,-9.017 v 0 c 0.46,0 0.926,0.031 1.39,0.091 v 0 c 5.69,0.765 9.694,5.989 8.934,11.681 v 0 c -0.758,5.688 -5.995,9.686 -11.681,8.928 v 0 c -5.688,-0.759 -9.694,-5.989 -8.936,-11.683 z" + id="path602" /> + <path + fill="#999999" + d="m 139.603,29.261 c 0.533,-0.08 1.061,-0.122 1.587,-0.122 v 0 c 5.044,0 9.472,3.679 10.262,8.818 v 0 c 0.87,5.681 -3.024,10.981 -8.703,11.852 v 0 c -5.672,0.87 -10.977,-3.021 -11.851,-8.698 v 0 c -0.868,-5.672 3.029,-10.981 8.705,-11.85 z" + id="path604" /> + <path + fill="#999999" + d="m 104.054,40.129 c 1.431,-0.675 2.944,-0.997 4.431,-0.997 v 0 c 3.898,0 7.627,2.2 9.404,5.956 v 0 c 2.454,5.19 0.236,11.387 -4.957,13.838 v 0 c -5.189,2.453 -11.388,0.236 -13.838,-4.959 v 0 c -2.45,-5.188 -0.233,-11.387 4.96,-13.838 z" + id="path606" /> + <path + fill="#999999" + d="m 229.183,60.114 c 2.055,-2.397 4.964,-3.626 7.892,-3.626 v 0 c 2.4,0 4.805,0.826 6.771,2.507 v 0 c 4.344,3.738 4.855,10.3 1.11,14.654 v 0 c -3.735,4.359 -10.301,4.859 -14.655,1.124 v 0 0 c -4.362,-3.741 -4.865,-10.305 -1.118,-14.659 z" + id="path608" /> + <path + fill="#999999" + d="m 73.081,60.649 c 1.985,-1.764 4.455,-2.639 6.917,-2.639 v 0 c 2.859,0 5.709,1.173 7.758,3.477 v 0 c 3.825,4.283 3.451,10.856 -0.833,14.676 v 0 0 C 82.641,79.984 76.068,79.61 72.249,75.324 v 0 C 68.424,71.042 68.797,64.47 73.08,60.649 v 0 z" + id="path610" /> + <path + fill="#999999" + d="m 253.916,83.886 c 1.746,-1.131 3.71,-1.675 5.647,-1.675 v 0 c 3.406,-0.001 6.744,1.67 8.734,4.736 v 0 0 0 c 3.114,4.821 1.751,11.253 -3.065,14.381 v 0 c -4.823,3.122 -11.255,1.753 -14.383,-3.062 v 0 0 c -3.114,-4.819 -1.749,-11.251 3.067,-14.38 z" + id="path612" /> + <path + fill="#999999" + d="m 49.17,89.077 c 1.969,-3.167 5.367,-4.914 8.837,-4.914 v 0 c 1.871,0 3.771,0.51 5.48,1.569 v 0 c 4.875,3.032 6.37,9.442 3.336,14.314 v 0 c -3.032,4.877 -9.438,6.374 -14.314,3.344 v 0 C 47.634,100.358 46.138,93.946 49.17,89.074 v 0 z" + id="path614" /> + <path + fill="#999999" + d="m 34.288,123.131 c 1.262,-4.621 5.453,-7.649 10.02,-7.649 v 0 c 0.907,0 1.832,0.118 2.752,0.369 v 0 c 5.536,1.515 8.792,7.235 7.277,12.776 v 0 c -1.515,5.527 -7.232,8.794 -12.769,7.27 v 0 c -5.541,-1.515 -8.796,-7.228 -7.28,-12.766 z" + id="path616" /> + <path + fill="#999999" + d="m 163.404,59.558 c 0.496,-3.7 3.666,-6.393 7.292,-6.391 v 0 c 0.329,0 0.653,0.02 0.991,0.062 v 0 0 0 c 4.028,0.542 6.864,4.247 6.318,8.279 v 0 c -0.535,4.032 -4.239,6.865 -8.267,6.329 v 0 c -4.042,-0.541 -6.879,-4.247 -6.334,-8.279 z" + id="path618" /> + <path + fill="#999999" + d="m 145.37,53.482 c 0.377,-0.056 0.751,-0.083 1.124,-0.083 v 0 c 3.575,-10e-4 6.715,2.607 7.271,6.251 v 0 c 0.622,4.025 -2.142,7.784 -6.165,8.4 v 0 c -4.022,0.618 -7.783,-2.146 -8.399,-6.167 v 0 c -0.618,-4.023 2.146,-7.781 6.169,-8.401 z" + id="path620" /> + <path + fill="#999999" + d="m 187.281,64.146 c 1.223,-2.734 3.915,-4.352 6.729,-4.352 v 0 c 1.01,0 2.029,0.208 3.008,0.646 v 0 0 0 c 3.71,1.669 5.374,6.03 3.704,9.74 v 0 c -1.659,3.711 -6.021,5.37 -9.738,3.702 v 0 c -3.712,-1.663 -5.373,-6.023 -3.703,-9.736 z" + id="path622" /> + <path + fill="#999999" + d="m 120.175,61.184 c 1.013,-0.475 2.086,-0.702 3.138,-0.702 v 0 c 2.762,0 5.412,1.557 6.668,4.221 v 0 c 1.738,3.678 0.165,8.067 -3.515,9.805 v 0 c -3.678,1.743 -8.069,0.17 -9.808,-3.509 v 0 c -1.737,-3.679 -0.164,-8.071 3.517,-9.813 v 0 c 0,-0.002 0,-0.002 0,-0.002 z" + id="path624" /> + <path + fill="#999999" + d="m 208.868,75.351 c 1.454,-1.699 3.514,-2.568 5.583,-2.568 v 0 c 1.698,-0.003 3.409,0.582 4.801,1.777 v 0 0 0 c 3.088,2.646 3.439,7.299 0.791,10.389 v 0 c -2.653,3.087 -7.304,3.443 -10.387,0.79 v 0 0 c -3.088,-2.647 -3.439,-7.297 -0.788,-10.388 z" + id="path626" /> + <path + fill="#999999" + d="m 98.219,75.731 c 1.407,-1.254 3.158,-1.868 4.902,-1.868 v 0 c 2.031,0 4.044,0.833 5.498,2.462 v 0 c 2.71,3.036 2.445,7.692 -0.591,10.402 v 0 c -3.038,2.71 -7.695,2.443 -10.402,-0.59 v 0 c -2.708,-3.036 -2.443,-7.695 0.593,-10.406 z" + id="path628" /> + <path + fill="#999999" + d="m 226.394,92.202 c 1.237,-0.801 2.632,-1.189 4.009,-1.189 v 0 c 2.414,0 4.769,1.185 6.184,3.36 v 0 c 2.214,3.414 1.243,7.976 -2.172,10.189 v 0 c -3.412,2.216 -7.98,1.245 -10.192,-2.167 v 0 c -2.215,-3.412 -1.245,-7.977 2.171,-10.193 z" + id="path630" /> + <path + fill="#999999" + d="M 81.267,95.877 C 82.666,93.634 85.07,92.4 87.535,92.4 v 0 c 1.328,0 2.668,0.36 3.878,1.111 v 0 c 3.461,2.145 4.519,6.695 2.372,10.148 v -0.004 0 c -2.15,3.457 -6.692,4.518 -10.147,2.367 v 0 C 80.18,103.877 79.124,99.336 81.267,95.877 Z" + id="path632" /> + <path + fill="#999999" + d="m 70.722,120.02 c 0.895,-3.275 3.866,-5.426 7.1,-5.426 v 0 c 0.645,0 1.303,0.087 1.951,0.263 v 0 c 3.925,1.076 6.237,5.128 5.158,9.057 v 0 c -1.068,3.919 -5.127,6.233 -9.051,5.152 v 0 c -3.925,-1.072 -6.234,-5.124 -5.158,-9.046 z" + id="path634" /> + <path + fill="#999999" + d="m 162.067,77.284 c 0.337,-2.466 2.439,-4.264 4.866,-4.264 v 0 c 0.219,0 0.438,0.014 0.662,0.048 v 0 c 2.688,0.358 4.579,2.828 4.215,5.518 v 0 c -0.353,2.69 -2.833,4.576 -5.524,4.215 v 0 c -2.687,-0.357 -4.571,-2.827 -4.219,-5.517 z" + id="path636" /> + <path + fill="#999999" + d="m 150.046,73.235 c 0.253,-0.037 0.501,-0.055 0.75,-0.055 v 0 c 2.387,0 4.479,1.738 4.85,4.168 v 0 c 0.411,2.682 -1.43,5.186 -4.112,5.596 h 0.001 v 0 c -2.682,0.415 -5.186,-1.427 -5.602,-4.109 v 0 c -0.408,-2.682 1.432,-5.19 4.113,-5.6 z" + id="path638" /> + <path + fill="#999999" + d="m 177.991,80.344 c 0.822,-1.825 2.611,-2.904 4.486,-2.904 v 0 c 0.666,0 1.355,0.142 2.012,0.437 v -0.002 0.002 -0.002 0 c 2.476,1.11 3.581,4.017 2.47,6.493 v 0 c -1.118,2.473 -4.019,3.58 -6.497,2.468 v 0 c -2.477,-1.11 -3.575,-4.02 -2.471,-6.492 z" + id="path640" /> + <path + fill="#999999" + d="m 133.25,78.37 c 0.677,-0.321 1.39,-0.473 2.094,-0.473 v 0 c 1.84,0 3.604,1.044 4.443,2.818 v 0 c 1.161,2.451 0.111,5.379 -2.343,6.541 v 0 c -2.451,1.158 -5.379,0.109 -6.542,-2.342 v 0 c -1.156,-2.457 -0.106,-5.381 2.347,-6.543 v 0 h 0.001 z" + id="path642" /> + <path + fill="#999999" + d="m 118.612,88.066 c 0.936,-0.833 2.103,-1.246 3.269,-1.246 v 0 c 1.352,0 2.697,0.556 3.668,1.645 v 0 c 1.802,2.021 1.626,5.13 -0.398,6.932 v 0 0 c -2.023,1.808 -5.13,1.633 -6.932,-0.393 v 0 c -1.807,-2.023 -1.633,-5.13 0.393,-6.938 z" + id="path644" /> + <path + fill="#999999" + d="m 204.07,99.05 c 0.819,-0.534 1.753,-0.79 2.67,-0.79 v 0 c 1.605,0 3.185,0.785 4.127,2.235 v 0 c 1.475,2.278 0.825,5.32 -1.448,6.797 v 0 c -2.269,1.478 -5.317,0.825 -6.796,-1.448 v 0 c -1.475,-2.276 -0.821,-5.319 1.447,-6.794 z" + id="path646" /> + <path + fill="#999999" + d="m 212.111,113.129 c 0.461,-0.139 0.933,-0.201 1.396,-0.201 v 0 c 2.114,0 4.072,1.384 4.704,3.526 v 0 c 0.767,2.602 -0.721,5.332 -3.325,6.099 v 0 c -2.596,0.77 -5.334,-0.717 -6.101,-3.322 v 0 c -0.766,-2.601 0.721,-5.332 3.326,-6.102 z" + id="path648" /> + <path + fill="#999999" + d="m 100.277,117.596 c 0.601,-2.183 2.576,-3.62 4.736,-3.62 v 0 c 0.428,0 0.868,0.061 1.297,0.181 v 0 c 2.62,0.716 4.157,3.418 3.44,6.032 v 0 0 c -0.713,2.621 -3.42,4.158 -6.031,3.438 v 0 c -2.616,-0.716 -4.159,-3.417 -3.442,-6.031 z" + id="path650" /> + <path + fill="#999999" + d="m 161.098,90.159 c 0.209,-1.565 1.559,-2.711 3.099,-2.711 v 0 c 0.132,0 0.271,0.009 0.419,0.029 v 0 c 1.713,0.226 2.902,1.799 2.686,3.508 v 0 c -0.23,1.711 -1.809,2.912 -3.518,2.684 v 0 0 c -1.713,-0.23 -2.913,-1.801 -2.686,-3.51 z" + id="path652" /> + <path + fill="#999999" + d="m 153.453,87.582 c 0.16,-0.023 0.317,-0.036 0.48,-0.036 v 0 c 1.513,0 2.844,1.107 3.081,2.654 v 0 c 0.261,1.705 -0.907,3.299 -2.611,3.56 v 0 c -1.705,0.262 -3.301,-0.911 -3.564,-2.616 v 0 c -0.263,-1.701 0.908,-3.296 2.614,-3.562 z" + id="path654" /> + <path + fill="#999999" + d="m 171.229,92.102 c 0.521,-1.156 1.653,-1.844 2.846,-1.844 v 0 c 0.43,0 0.868,0.091 1.287,0.281 v 0 0 0 c 1.57,0.702 2.272,2.551 1.567,4.126 v 0 c -0.708,1.573 -2.557,2.277 -4.13,1.568 h -0.003 v 0 c -1.57,-0.705 -2.272,-2.554 -1.567,-4.131 z" + id="path656" /> + <path + fill="#999999" + d="m 133.46,97.019 c 0.594,-0.534 1.336,-0.795 2.077,-0.795 v 0 c 0.86,0 1.716,0.354 2.331,1.047 v 0 c 1.154,1.286 1.042,3.259 -0.25,4.411 v 0 c -1.285,1.146 -3.26,1.033 -4.411,-0.252 v 0 c -1.144,-1.289 -1.035,-3.264 0.253,-4.411 z" + id="path658" /> + <path + fill="#999999" + d="m 187.817,104.002 c 0.524,-0.34 1.109,-0.501 1.691,-0.501 v 0 c 1.031,0 2.029,0.501 2.623,1.421 v 0 0 0 c 0.939,1.449 0.526,3.386 -0.92,4.323 v 0 c -1.446,0.938 -3.376,0.527 -4.317,-0.922 v 0 c -0.943,-1.446 -0.523,-3.385 0.923,-4.321 z" + id="path660" /> + <path + fill="#999999" + d="m 126.275,105.558 c 0.589,-0.947 1.612,-1.474 2.656,-1.475 v 0 c 0.563,0 1.134,0.157 1.647,0.472 v 0 c 1.466,0.916 1.911,2.837 1.004,4.302 v 0 c -0.91,1.466 -2.838,1.917 -4.303,1.009 v 0 c -1.465,-0.915 -1.915,-2.843 -1.004,-4.308 z" + id="path662" /> + <path + fill="#999999" + d="m 192.923,112.959 c 0.3,-0.09 0.595,-0.13 0.888,-0.13 v 0 c 1.352,0 2.596,0.88 2.992,2.24 v 0 0 0 0 c 0.49,1.655 -0.458,3.394 -2.104,3.881 v 0 c -1.658,0.488 -3.395,-0.459 -3.882,-2.112 v 0 c -0.489,-1.656 0.456,-3.393 2.106,-3.879 z" + id="path664" /> + <path + fill="#999999" + d="m 121.802,115.796 c 0.381,-1.387 1.637,-2.302 3.012,-2.302 v 0 c 0.271,0 0.55,0.04 0.823,0.113 v 0 c 1.666,0.457 2.646,2.175 2.189,3.843 v 0 c -0.456,1.661 -2.177,2.641 -3.838,2.187 v 0 c -1.664,-0.458 -2.643,-2.177 -2.186,-3.841 z" + id="path666" /> + <path + fill="#999999" + d="m 238.457,113.321 c 0.688,-0.206 1.39,-0.306 2.082,-0.306 v 0 c 3.182,0 6.116,2.08 7.064,5.29 v 0 0 0 c 1.155,3.901 -1.077,7.996 -4.979,9.149 v 0 c -3.905,1.145 -8,-1.083 -9.155,-4.981 v 0 0 c -1.145,-3.902 1.082,-8.003 4.988,-9.152 z" + id="path668" /> + <rect + x="265.935" + y="149.649" + fill="#0067b1" + width="17.181" + height="68.734001" + id="rect670" /> + <line + fill="#0067b1" + x1="109.997" + y1="184.01199" + x2="109.997" + y2="184.01199" + id="line672" /> + <path + fill="#0067b1" + d="m 58.011,184.012 c 0,-4.741 3.851,-8.59 8.597,-8.59 h 51.979 c 1.214,-0.006 2.233,-0.47 3.04,-1.258 v 0 c 0.787,-0.804 1.25,-1.829 1.255,-3.041 v 0 c -0.004,-1.217 -0.468,-2.234 -1.255,-3.036 v 0 c -0.807,-0.788 -1.826,-1.252 -3.04,-1.258 v 0 H 68.321 c -4.753,0.004 -8.982,1.909 -12.107,5.023 v 0 c -3.12,3.137 -5.021,7.387 -5.031,12.159 v 0 c 0.01,4.782 1.912,9.021 5.031,12.159 v 0 c 3.125,3.126 7.354,5.019 12.107,5.021 v 0 h 71.793 v 0 17.192 H 68.321 c -0.005,0 -0.006,0 -0.013,0 v 0 c -9.452,0 -18.082,-3.871 -24.261,-10.077 v 0 C 37.852,202.111 33.998,193.471 34.004,184.011 v 0 c -0.006,-9.461 3.848,-18.1 10.043,-24.292 v 0 c 6.184,-6.214 14.816,-10.074 24.273,-10.07 h 50.265 c 5.903,-0.004 11.333,2.407 15.186,6.284 v 0 c 3.877,3.862 6.297,9.286 6.294,15.189 v 0 c 0.003,5.912 -2.417,11.334 -6.294,15.196 v 0 c -3.853,3.861 -9.273,6.282 -15.174,6.282 H 66.608 v 0 c -4.746,0.002 -8.597,-3.837 -8.597,-8.588 z" + id="path674" /> + <path + fill="#0067b1" + d="m 173.391,184.012 c 0,4.751 3.839,8.59 8.591,8.59 l 51.973,0.002 c 1.21,0.004 2.243,0.468 3.042,1.258 v 0 c 0.788,0.81 1.254,1.826 1.254,3.041 v 0 c 0,1.213 -0.466,2.231 -1.254,3.033 v 0 c -0.799,0.793 -1.832,1.254 -3.042,1.256 v 0 h -50.261 c -4.762,-0.002 -8.982,-1.895 -12.114,-5.021 v 0 c -3.109,-3.137 -5.017,-7.375 -5.02,-12.159 v 0 c 0.003,-4.772 1.91,-9.021 5.02,-12.159 v 0 c 3.132,-3.114 7.353,-5.018 12.114,-5.021 v 0 h 71.786 v -0.002 -17.18 h -71.786 c -0.006,0 -0.006,0 -0.016,0 v 0 c -9.45,0 -18.079,3.861 -24.255,10.068 v 0 c -6.205,6.194 -10.052,14.835 -10.049,24.294 v 0 c -0.003,9.46 3.844,18.1 10.049,24.295 v 0 c 6.18,6.21 14.814,10.081 24.271,10.077 h 50.261 c 5.913,0.004 11.336,-2.418 15.197,-6.296 v 0 c 3.864,-3.861 6.287,-9.284 6.281,-15.186 v 0 c 0.006,-5.902 -2.417,-11.324 -6.281,-15.187 v 0 c -3.861,-3.873 -9.275,-6.294 -15.184,-6.294 h -51.986 v 0 c -4.753,0.001 -8.591,3.85 -8.591,8.591 z" + id="path676" /> + <path + fill="#0067b1" + d="m 283.916,122.026 c 0,5.746 -4.654,10.403 -10.402,10.403 -5.736,0 -10.391,-4.657 -10.391,-10.403 0,-5.74 4.654,-10.396 10.391,-10.396 5.748,-10e-4 10.402,4.656 10.402,10.396 z" + id="path678" /> + <path + fill="#999999" + d="m 218.612,48.555 c 0,5.747 -4.654,10.402 -10.402,10.402 -5.736,0 -10.391,-4.656 -10.391,-10.402 0,-5.74 4.654,-10.396 10.391,-10.396 5.748,0 10.402,4.656 10.402,10.396 z" + id="path680" /> + <circle + fill="#999999" + cx="196.104" + cy="91.010002" + r="4.9060001" + id="circle682" /> + <circle + fill="#999999" + cx="111.483" + cy="104.092" + r="4.9060001" + id="circle684" /> + <circle + fill="#999999" + cx="182.75101" + cy="98.890999" + r="3.1259999" + id="circle686" /> + <circle + fill="#999999" + cx="144.103" + cy="93.674004" + r="3.1259999" + id="circle688" /> + </g> + <switch + id="switch1196" + transform="matrix(0.51790051,0,0,0.51790051,84.950238,76.684273)"> + <g + id="g1194"> + <g + id="g1182"> + <path + fill="#545454" + d="M 50.751,48.727 V 12.472 h 7.251 v 17.547 c 1.885,-2.32 4.544,-3.094 7.299,-3.094 6.042,0 10.586,5.269 10.586,11.167 0,5.898 -4.543,11.118 -10.585,11.118 -2.755,0 -5.849,-0.87 -7.299,-3.046 v 2.562 h -7.252 z m 12.327,-5.318 c 2.9,0 5.076,-2.514 5.076,-5.317 0,-2.803 -2.175,-5.317 -5.076,-5.317 -2.901,0 -5.076,2.514 -5.076,5.317 0,2.803 2.176,5.317 5.076,5.317 z" + id="path1170" /> + <path + fill="#545454" + d="m 84.35,15.855 c 2.32,0 4.254,1.885 4.254,4.254 0,2.32 -1.934,4.254 -4.254,4.254 -2.369,0 -4.254,-1.934 -4.254,-4.254 0,-2.368 1.885,-4.254 4.254,-4.254 z M 80.724,48.727 V 27.409 h 7.251 v 21.318 z" + id="path1172" /> + <path + fill="#545454" + d="m 115.819,48.727 h -7.25 V 36.642 c 0,-2.514 -0.967,-3.867 -3.239,-3.867 -2.272,0 -4.061,2.417 -4.061,5.317 V 48.727 H 94.018 V 27.409 h 7.251 v 2.61 c 1.45,-1.837 3.722,-3.094 6.526,-3.094 5.704,0 8.024,3.916 8.024,9.716 z" + id="path1174" /> + <path + fill="#545454" + d="m 144.826,48.727 h -7.251 v -2.562 c -1.45,2.176 -4.592,3.046 -7.299,3.046 -6.043,0 -10.587,-5.221 -10.587,-11.118 0,-5.897 4.544,-11.167 10.587,-11.167 2.707,0 5.414,0.773 7.299,3.094 V 12.472 h 7.251 z M 132.499,32.774 c -2.9,0 -5.075,2.514 -5.075,5.317 0,2.803 2.175,5.317 5.075,5.317 2.9,0 5.076,-2.514 5.076,-5.317 0,-2.803 -2.176,-5.317 -5.076,-5.317 z" + id="path1176" /> + <path + fill="#545454" + d="m 173.639,38.962 h -16.532 c 0,2.466 1.74,5.075 4.592,5.075 2.562,0 4.158,-1.691 4.206,-3.238 h 7.396 c -1.256,5.607 -5.801,8.411 -11.456,8.411 -7.348,0 -12.423,-4.351 -12.423,-11.118 0,-6.671 5.269,-11.167 12.423,-11.167 6.478,0 11.843,3.867 11.843,10.683 -10e-4,0.435 -0.049,0.919 -0.049,1.354 z m -6.913,-3.432 c 0,0 -0.338,-3.964 -4.736,-3.964 -4.545,0 -4.786,3.964 -4.786,3.964 z" + id="path1178" /> + <path + fill="#545454" + d="m 185.532,38.092 v 10.635 h -7.251 V 27.409 h 7.251 v 2.61 c 1.111,-1.595 2.949,-3.094 5.607,-3.094 0.629,0 1.596,0.193 2.176,0.483 v 6.574 h -0.098 c -0.725,-0.87 -1.788,-1.208 -2.9,-1.208 -2.707,0 -4.785,2.756 -4.785,5.318 z" + id="path1180" /> + </g> + <circle + fill="none" + stroke="#f5a252" + stroke-width="4.8342" + stroke-miterlimit="10" + cx="27.879" + cy="23.938999" + r="9.5419998" + id="circle1184" /> + <circle + fill="none" + stroke="#579aca" + stroke-width="4.8342" + stroke-miterlimit="10" + cx="27.879" + cy="42.499001" + r="9.5430002" + id="circle1186" /> + <circle + fill="none" + stroke="#e66581" + stroke-width="4.8342" + stroke-miterlimit="10" + cx="18.551001" + cy="33.289001" + r="9.5430002" + id="circle1188" /> + <path + fill="none" + stroke="#579aca" + stroke-width="4.8342" + stroke-miterlimit="10" + d="m 20.196,36.836 c 0.759,-1.031 1.74,-1.927 2.921,-2.607 4.566,-2.63 10.401,-1.06 13.031,3.507" + id="path1190" /> + <path + fill="none" + stroke="#f5a252" + stroke-width="4.8342" + stroke-miterlimit="10" + d="M 19.61,28.701 C 16.98,24.135 18.549,18.3 23.117,15.669 c 4.567,-2.63 10.401,-1.059 13.031,3.508" + id="path1192" /> + </g> + </switch> + </g> +</svg> diff --git a/common/playbooks/files/egi-binder-page.html b/common/playbooks/files/egi-binder-page.html new file mode 100644 index 0000000000000000000000000000000000000000..8495a4997f168a57ba18622942420b430603e904 --- /dev/null +++ b/common/playbooks/files/egi-binder-page.html @@ -0,0 +1,18 @@ +<!-- htmlhint doctype-first:false --> +{% extends "templates/page.html" %} + +{% block meta_social %} +{# Social media previews #} +<meta property="og:title" content="EGI Replay"> +<meta property="og:image" content="https://replay.egi-test.civ.zcu.cz/hub/hub/static/images/egi-icon-replay.svg"> +<meta property="og:description" content="Reproducible, sharable, open, interactive computing environments."> +<meta property="og:image:width" content="1334"> +<meta property="og:image:height" content="700"> +<meta property="og:image:alt" content="EGI Replay service logo" /> +<meta name="twitter:card" content="summary_large_image"> +{% endblock meta_social %} + +{% block logo_image %}"{{ EXTRA_STATIC_URL_PREFIX }}egi-binder-logo.svg"{% endblock logo_image %} + +<!-- Remove the footer part --> +{% block footer %}{% endblock footer %} diff --git a/common/playbooks/files/egi-icon-replay.svg b/common/playbooks/files/egi-icon-replay.svg new file mode 100644 index 0000000000000000000000000000000000000000..4f9b34d909bf0b0f627febbcb8d95a68e538ff52 --- /dev/null +++ b/common/playbooks/files/egi-icon-replay.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><svg id="Laag_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 43.76 62.52"><defs><style>.cls-1{stroke:#ff7f00;}.cls-1,.cls-2{fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:3px;}.cls-2{stroke:#0062ab;}</style></defs><g id="Laag_1-2"><g><rect class="cls-2" x="-7.88" y="10.88" width="59.52" height="40.76" rx="2.98" ry="2.98" transform="translate(-9.38 53.14) rotate(-90)"/><g><circle class="cls-2" cx="21.88" cy="44.4" r="8.08"/><path class="cls-1" d="M19.75,29.13c1.09,1.39,3.18,1.39,4.27,0,2.39-3.05,5.95-8.06,5.95-11.02,0-4.46-3.62-8.08-8.08-8.08s-8.08,3.62-8.08,8.08c0,2.96,3.55,7.98,5.95,11.02Z"/></g></g></g></svg> \ No newline at end of file diff --git a/common/playbooks/files/egi-replay-privacy-policy.html b/common/playbooks/files/egi-replay-privacy-policy.html new file mode 100644 index 0000000000000000000000000000000000000000..68c66f2515f4667c69dc4748ba92701fa66a4cb2 --- /dev/null +++ b/common/playbooks/files/egi-replay-privacy-policy.html @@ -0,0 +1,372 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + + <title>Privacy policy</title> + <meta http-equiv="X-UA-Compatible" content="chrome=1" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + + <link + rel="stylesheet" + href="/hub/static/css/style.min.css" + type="text/css" + /> + + <link rel="stylesheet" href="/policies/style.css" type="text/css" /> + </head> + + <body> + <nav class="navbar navbar-default"> + <div class="container-fluid"> + <div class="navbar-header"> + <span id="jupyterhub-logo" class="pull-left"> + <a href="/hub/" + ><img + src="/hub/logo" + alt="JupyterHub" + class="jpy-logo" + title="Home" + /></a> + </span> + </div> + + <div class="collapse navbar-collapse" id="thenavbar"> + <ul class="nav navbar-nav navbar-right"> + <li> + <span id="user-guide"> + <a + role="button" + class="navbar-btn btn-sm btn btn-egi" + href="https://docs.egi.eu/users/dev-env/replay/" + > + <i aria-hidden="true" class="fa fa-book"></i> User Guide</a + > + </span> + </li> + </ul> + </div> + </div> + </nav> + + <div class="container"> + <h1>Privacy Notice</h1> + <table class="table"> + <tbody> + <tr> + <th>Name of the Service</th> + <td>Replay</td> + </tr> + <tr> + <th>Description of the Service</th> + <td> + <p> + The EGI Replay service (hereinafter referred to as: “the + service” or “Replay”) allows reproducing and sharing custom + computing environments for replicating the execution of analysis + in a notebooks-based platform. + </p> + <p> + This privacy notice describes how we, the EGI Foundation + (hereinafter referred to as "we" or "the Data Controller"), + collect and process data by which you can be personally + identified ("Personal Data") when you use the service. + </p> + </td> + </tr> + + <tr> + <th>Data controller</th> + <td> + <address class="vcard"> + <span class="fn org">EGI Foundation</span> + <span class="street-address">Science Park 140</span> + <span class="postal-code">1098 XG</span> + <span class="locality">Amsterdam</span> + <span class="country-name">Netherlands</span> + </address> + </td> + </tr> + + <tr> + <th>Data Protection Officer</th> + <td> + <address class="vcard"> + <span class="fn org" + >EGI Foundation Data Protection Officer</span + > + <span class="street-address">Science Park 140</span> + <span class="postal-code">1098 XG</span> + <span class="locality">Amsterdam</span> + <span class="country-name">Netherlands</span> + <span class="email" + >E-mail: <a href="mailto:dpo@egi.eu">dpo@egi.eu</a></span + > + </address> + </td> + </tr> + + <tr> + <th>Jurisdiction and supervisory authority</th> + <td> + <p>Jurisdiction: NL, Netherlands</p> + + <p> + EGI Foundation's lead supervisory authority is the Dutch Data + Protection Authority. They can be contacted at + <a + href="https://autoriteitpersoonsgegevens.nl/en/contact-dutch-dpa/contact-us" + >https://autoriteitpersoonsgegevens.nl/en/contact-dutch-dpa/contact-us</a + > + </p> + </td> + </tr> + + <tr> + <th>Personal data processed</th> + <td> + <p> + In addition to any personal data incorporated in notebooks + managed by end users using the Replay service, the following + categories of personal data may be processed by the EGI + Foundation as part of providing the aforementioned service: + </p> + + <strong>Identification data:</strong> + <ul> + <li>Identification number</li> + <li>E-mail address</li> + <li>Affiliation</li> + <li>IP address</li> + </ul> + + <strong>Behavioural data:</strong> + <ul> + <li>Usage data</li> + <li>Technical logs with timestamps</li> + </ul> + + <strong>Data allowing conclusions on the personality:</strong> + <ul> + <li>Membership information on roles, groups and communities</li> + </ul> + </td> + </tr> + + <tr> + <th>Purpose of the processing of personal data</th> + <td> + <p> + The purpose of the collection, processing and use of the + personal data mentioned above is: + </p> + + <ul> + <li> + To provide the service functions, i.e. users to manage their + notebooks on the resources they can access and allowing + administrators to manage the service and the user groups. + </li> + <li> + Identify the users or the administrators accessing the service + and track usage of resources for accounting, security + management and maintaining service stability and performance. + </li> + </ul> + </td> + </tr> + + <tr> + <th>Legal basis</th> + <td> + The legal basis for processing personal data is: Legitimate + interests pursued by the controller or by a third party according + to Art. 6 (1) (f) GDPR. + </td> + </tr> + + <tr> + <th>Third parties to whom personal data is disclosed</th> + <td> + <p> + Personal data will not be used beyond the original purpose of + their acquisition. If a forwarding to third parties should be + necessary to answer an inquiry or to carry out a service, the + consent of the data subject is considered to have been given + when using the respective function or service. In particular, + the data you provide to us will not be used for marketing. + </p> + + <p> + For the purpose given in this privacy policy, personal data may + be passed to the following third parties: + </p> + + <strong> Within the EU / EEA: </strong> + + <ul> + <li> + CESNET (resource provider, service administrator, + sub-contracted data processor) + </li> + <li> + Suppliers supporting the customer: Provision of cloud + resources: a comprehensive list of providers contributing to + the federation's cloud resources can be found here: + <a href="https://www.egi.eu/federation/egi-federated-cloud/" + >https://www.egi.eu/federation/egi-federated-cloud/</a + > + </li> + <li> + The records of your use and technical log files produced by + the Service components may be shared, via secured mechanisms, + for security incident response purposes with other authorised + participants in the academic and research distributed digital + infrastructures authorised by EGI Foundation governance, only + for the same purposes and only as far as necessary to provide + the incident response capability where doing so is likely to + assist in the investigation of suspected misuse of + Infrastructure resources. + </li> + </ul> + + <strong> Outside the EU / EEA: </strong> + + <ul> + <li> + Suppliers supporting the customer: Provision of cloud + resources: a comprehensive list of providers contributing to + the federation's cloud resources can be found here: + <a href="https://www.egi.eu/federation/egi-federated-cloud/" + >https://www.egi.eu/federation/egi-federated-cloud/</a + > + </li> + </ul> + + <p> + Any data transfer to a third country outside the EU or the EEA + only takes place under the conditions contained in Chapter V of + the GDPR and in compliance with the provisions of this privacy + policy and any related policies adopted by the EGI Federation. + </p> + </td> + </tr> + + <tr> + <th>Your rights</th> + <td> + <p> + You can exercise the following rights at any time by contacting + our data protection officer using the contact details provided + in the Data Protection Officer section: + </p> + + <ul> + <li> + Information about your data stored with us and their + processing + </li> + <li>Correction of incorrect personal data</li> + <li>Deletion of your data stored by us</li> + <li> + Restriction of data processing, if we are not yet allowed to + delete your data due to legal obligations + </li> + <li>Objection to the processing of your data by us</li> + <li>Data portability</li> + </ul> + + <p> + You can complain at any time to the supervisory data protection + authority (DPA) responsible for you. Your responsible DPA + depends on your country and state of residence, of your + workplace or of the presumed violation. A list of the + supervisory authorities with addresses can be found at + <a href="https://edpb.europa.eu/about-edpb/board/members_en" + >https://edpb.europa.eu/about-edpb/board/members_en</a + >. + </p> + + <p> + You can contact EGI Foundation's lead supervising authority + using the contact details provided in the Jurisdiction and + Supervisory Authority section. + </p> + </td> + </tr> + + <tr> + <th>Data retention and deletion</th> + <td> + The records of your use and technical log files produced by the + service components will be deleted or anonymised after, at most, + 18 months. + </td> + </tr> + + <tr> + <th>Security</th> + <td> + <p> + We take appropriate technical and organisational measures to + ensure data security and the protection against accidental or + unlawful destruction, accidental loss, alteration, unauthorised + disclosure or access. + </p> + + <p> + A comprehensive overview of the technical and organisational + measures taken by EGI Foundation can be found at + <a + href="https://documents.egi.eu/public/ShowDocument?docid=3737" + >EGI Documentation Database</a + >. + </p> + </td> + </tr> + + <tr> + <th>Data Protection Code of Conduct</th> + <td> + <p> + EGI Foundation is conforming to GEANT Code of Conduct and your + personal data will be processed in accordance with the + <a + href="http://www.geant.net/uri/dataprotection-code-of-conduct/v1" + >Code of Conduct for Service Providers</a + > + and the + <a + href="https://documents.egi.eu/public/ShowDocument?docid=2732" + >EGI-doc-2732-v3: Policy on the Processing of Personal + Data.</a + > + </p> + </td> + </tr> + + <tr> + <th>Acknowledgement</th> + <td> + This privacy notice is based on the + <a href="https://aarc-project.eu/policies/policy-development-kit/" + >AARC Policy development kit</a + > + (licensed under + <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" + >CC BY-NC-SA 4.0</a + >) + </td> + </tr> + </tbody> + </table> + </div> + + <footer class="footer"> + <div class="container text-center"> + <a href="/policies/privacy-policy.html">Privacy Notice</a> | + <a href="/policies/terms-of-use.html">Terms of Use</a> + </div> + </footer> + </body> +</html> diff --git a/common/playbooks/files/egi-replay-terms-of-use.html b/common/playbooks/files/egi-replay-terms-of-use.html new file mode 100644 index 0000000000000000000000000000000000000000..3b52866df6fd69a29289132f3f543ce42434aafd --- /dev/null +++ b/common/playbooks/files/egi-replay-terms-of-use.html @@ -0,0 +1,132 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + + <title>Terms of Use</title> + <meta http-equiv="X-UA-Compatible" content="chrome=1" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + + <link + rel="stylesheet" + href="/hub/static/css/style.min.css" + type="text/css" + /> + + <link rel="stylesheet" href="/policies/style.css" type="text/css" /> + </head> + + <body> + <nav class="navbar navbar-default"> + <div class="container-fluid"> + <div class="navbar-header"> + <span id="jupyterhub-logo" class="pull-left"> + <a href="/hub/" + ><img + src="/hub/logo" + alt="JupyterHub" + class="jpy-logo" + title="Home" + /></a> + </span> + </div> + + <div class="collapse navbar-collapse" id="thenavbar"> + <ul class="nav navbar-nav navbar-right"> + <li> + <span id="user-guide"> + <a + role="button" + class="navbar-btn btn-sm btn btn-egi" + href="https://docs.egi.eu/users/dev-env/replay/" + > + <i aria-hidden="true" class="fa fa-book"></i> User Guide</a + > + </span> + </li> + </ul> + </div> + </div> + </nav> + + <div class="container"> + <h1>EGI Replay Acceptable Use Policy and Conditions of Use (AUP)</h1> + + <p> + This Acceptable Use Policy and Conditions of Use ("AUP") defines the + rules and conditions that govern your access to and use (including + transmission, processing, and storage of data) of the resources and + services ("Services") as granted by the EGI Federation, and the Virtual + Organisation to which you belong, for the purpose of meeting the goals + of EGI, namely to deliver advanced computing services to support + researchers, multinational projects and research infrastructures, and + the goals of your Virtual Organisation or Research Community. + </p> + <ol> + <li> + You shall only use the Services in a manner consistent with the + purposes and limitations described above; you shall show consideration + towards other users including by not causing harm to the Services; you + have an obligation to collaborate in the resolution of issues arising + from your use of the Services. + </li> + <li> + You shall only use the Services for lawful purposes and not breach, + attempt to breach, nor circumvent administrative or security controls. + </li> + <li> + You shall respect intellectual property and confidentiality + agreements. + </li> + <li> + You shall protect your access credentials (e.g. passwords, private + keys or multi-factor tokens); no intentional sharing is permitted. + </li> + <li> + You shall keep your registered information correct and up to date. + </li> + <li> + You shall promptly report known or suspected security breaches, + credential compromise, or misuse to the security contact stated below; + and report any compromised credentials to the relevant issuing + authorities. + </li> + <li> + Reliance on the Services shall only be to the extent specified by any + applicable service level agreements listed below. Use without such + agreements is at your own risk. + </li> + <li> + Your personal data will be processed in accordance with the privacy + statements referenced below. + </li> + <li> + Your use of the Services may be restricted or suspended, for + administrative, operational, or security reasons, without prior notice + and without compensation. + </li> + <li> + If you violate these rules, you may be liable for the consequences, + which may include your account being suspended and a report being made + to your home organisation or to law enforcement. + </li> + </ol> + + <p> + The administrative contact for this AUP is: + <a href="mailto:operations@egi.eu">operations@egi.eu</a><br /> + The security contact for this AUP is: + <a href="mailto:abuse@egi.eu">abuse@egi.eu</a><br /> + The Privacy Notice is located at + <a href="/policies/privacy-policy.html">Privacy Notice</a><br /> + </p> + </div> + + <footer class="footer"> + <div class="container text-center"> + <a href="/policies/privacy-policy.html">Privacy Notice</a> | + <a href="/policies/terms-of-use.html">Terms of Use</a> + </div> + </footer> + </body> +</html> diff --git a/common/playbooks/files/egi-style.css b/common/playbooks/files/egi-style.css new file mode 100644 index 0000000000000000000000000000000000000000..419f1fe91ede0d3954a9cef456fec89c2e747e65 --- /dev/null +++ b/common/playbooks/files/egi-style.css @@ -0,0 +1,21 @@ +/* Minimal extra styles for policy files */ + +html { + position: relative; + min-height: 100%; +} + +body { + margin-bottom: 60px; /* Margin bottom by footer height */ +} + +.footer { + position: absolute; + bottom: 0; + width: 100%; + height: 60px; /* Set the fixed height of the footer here */ +} + +address { + white-space: pre-line; +} diff --git a/common/playbooks/files/etc/cron.d/binder-socket-cleaner-dind b/common/playbooks/files/etc/cron.d/binder-socket-cleaner-dind new file mode 100644 index 0000000000000000000000000000000000000000..a4d68884eb87c4c00ad68e41ec3a33fc5bcaecb9 --- /dev/null +++ b/common/playbooks/files/etc/cron.d/binder-socket-cleaner-dind @@ -0,0 +1 @@ +*/2 * * * * root test -d /var/run/dind/docker.sock && rm -rfv /var/run/dind/docker.sock diff --git a/common/playbooks/files/etc/cron.d/binder-socket-cleaner-pink b/common/playbooks/files/etc/cron.d/binder-socket-cleaner-pink new file mode 100644 index 0000000000000000000000000000000000000000..c94c458e328b6fc847728496804a5649db6d668d --- /dev/null +++ b/common/playbooks/files/etc/cron.d/binder-socket-cleaner-pink @@ -0,0 +1 @@ +*/2 * * * * root test -d /var/run/pink/podman.sock && rm -rfv /var/run/pink/podman.sock diff --git a/egi-devel/inventory/99-all.yaml b/egi-devel/inventory/99-all.yaml index 1a920c710e941c6989cb13657a7337b4970bb9fe..636def6f9533749d7653422568c151ad6998b8ad 100644 --- a/egi-devel/inventory/99-all.yaml +++ b/egi-devel/inventory/99-all.yaml @@ -19,6 +19,7 @@ all: site_name: egi-devel vault_mount_point: secrets/users/e1662e20-e34b-468c-b0ce-d899bc878364@egi.eu/egi-devel + binder_hostname: binder-dev.egi.zcu.cz notebooks_hostname: notebooks-dev.egi.zcu.cz grafana_hostname: grafana.notebooks-dev.egi.zcu.cz nexus_hostname: nexus.notebooks-dev.egi.zcu.cz diff --git a/egi-devel/playbooks/binder.yaml b/egi-devel/playbooks/binder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c23dbe7986e05f6c9ccbbb94c15975b71eafaea2 --- /dev/null +++ b/egi-devel/playbooks/binder.yaml @@ -0,0 +1,223 @@ +--- +- name: Binder deployment + hosts: master + become: true + vars: + nexus_secrets: "{{ lookup('community.hashi_vault.hashi_vault', (vault_mount_point, 'nexus') | join('/'), token_validate=false) }}" + secrets: "{{ lookup('community.hashi_vault.hashi_vault', (vault_mount_point, 'binder') | join('/'), token_validate=false) }}" + tasks: + - name: Debug Repository Secrets + debug: + msg: "{{ item.key }} = {{ item.value }}" + loop: "{{ nexus_secrets | dict2items }}" + - name: Debug Binder Secrets + debug: + msg: "{{ item.key }} = {{ item.value }}" + loop: "{{ secrets | dict2items }}" + - name: Configure jupyterhub helm repo + shell: |- + helm repo add jupyterhub https://jupyterhub.github.io/helm-chart/ + helm repo update + changed_when: true + when: "'jupyterhub' not in ansible_local.helm_repos | map(attribute='name') | list" + - name: Configure secrets management for the binder + vars: + name: binder + shell: |- + kubectl create ns {{ name }} 2>/dev/null || true + kubectl apply -f - << EOF + --- + kind: Role + apiVersion: rbac.authorization.k8s.io/v1 + metadata: + name: hub-secrets + namespace: {{ name }} + rules: + - apiGroups: [""] # "" indicates the core API group + resources: ["secrets"] + verbs: ["get", "watch", "list", "create", "delete", "patch", "update"] + --- + kind: RoleBinding + apiVersion: rbac.authorization.k8s.io/v1 + metadata: + name: hub-secrets + namespace: {{ name }} + subjects: + - kind: ServiceAccount + name: hub + namespace: {{ name }} + roleRef: + kind: Role + name: hub-secrets + apiGroup: rbac.authorization.k8s.io + EOF + environment: + KUBECONFIG: /etc/kubernetes/admin.conf + PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + changed_when: true + when: true + - name: Configure EGI binder customisations + vars: + name: binder + shell: |- + kubectl apply -f - << EOF + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: egi-binder-templates + namespace: {{ name }} + data: + page.html: > + {{ lookup('file', 'files/egi-binder-page.html') | indent(width=10) }} + --- + apiVersion: v1 + kind: ConfigMap + metadata: + name: egi-binder-static + namespace: {{ name }} + data: + egi-binder-logo.svg: > + {{ lookup('file', 'files/egi-binder-logo.svg') | indent(width=10) }} + EOF + environment: + KUBECONFIG: /etc/kubernetes/admin.conf + PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + changed_when: true + when: true + - name: Copy binder config file to master + template: + src: templates/binder.yaml + dest: /tmp/binder.yaml + mode: 0600 + - name: Binder + vars: + # https://jupyterhub.github.io/helm-chart/#development-releases-binderhub + # see also https://github.com/jupyterhub/binderhub/blob/master/helm-chart/binderhub/Chart.yaml for compatibility with jupyterhub + # EGI production version + # version: 1.0.0-0.dev.git.2874.h2811d52 # 2022-11-25 (2.0.0) + # version: 1.0.0-0.dev.git.3500.hf2f1272 # 2024-08-01 (older) + # version: 1.0.0-0.dev.git.3550.ha957bf05 # 2025-01-03 can't launch (fixed) + version: 1.0.0-0.dev.git.3553.h57e3b3ae # 2025-01-03 can't launch (fixed) + # version: 1.0.0-0.dev.git.3653.hb72cd888 # 2025-01-03 no GUI + # version: 1.0.0-0.dev.git.3667.h65f807c1 # 2025-01-15 no GUI + # version: 1.0.0-0.dev.git.3680.he8e336dd # 2025-01-30 no GUI + # version: 1.0.0-0.dev.git.3709.h61bbc623 # 2025-03-13 no GUI + # version: 1.0.0-0.dev.git.3714.h1a177a35 # 2025-03-13 no GUI + shell: |- + helm status --namespace binder binder + if [ $? -ne 0 ]; then + helm install binder jupyterhub/binderhub --version={{ version }} --namespace=binder -f /tmp/binder.yaml + else + helm upgrade binder jupyterhub/binderhub --version={{ version }} --namespace=binder -f /tmp/binder.yaml + fi + environment: + KUBECONFIG: /etc/kubernetes/admin.conf + PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + changed_when: true + when: true + - name: Create policy files + vars: + # binder_config: templates/binder.yaml + namespace: binder + ingress_hostname: "{{ binder_hostname }}" + shell: |- + kubectl apply -f - << EOF + --- + kind: ConfigMap + apiVersion: v1 + metadata: + name: policies + namespace: {{ namespace }} + data: + privacy-policy.html: > + {{ lookup('file', 'files/egi-replay-privacy-policy.html') | indent(width=10) }} + terms-of-use.html: > + {{ lookup('file', 'files/egi-replay-terms-of-use.html') | indent(width=10) }} + style.css: > + {{ lookup('file', 'files/egi-style.css') | indent(width=10) }} + --- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: policies + namespace: {{ namespace }} + spec: + selector: + matchLabels: + app: policies + replicas: 1 + template: + metadata: + labels: + app: policies + spec: + containers: + - name: nginx + image: nginx:1.27.4 + ports: + - containerPort: 80 + volumeMounts: + - name: config + mountPath: /usr/share/nginx/html/policies + volumes: + - name: config + configMap: + name: policies + --- + apiVersion: v1 + kind: Service + metadata: + namespace: {{ namespace }} + name: policies + labels: + app: policies + spec: + ports: + - name: http + port: 80 + protocol: TCP + selector: + app: policies + --- + apiVersion: networking.k8s.io/v1 + kind: Ingress + metadata: + annotations: + kubernetes.io/ingress.class: nginx + labels: + component: ingress + name: policies + namespace: {{ namespace }} + spec: + rules: + - host: {{ ingress_hostname }} + http: + paths: + - backend: + service: + name: policies + port: + name: http + path: /policies + pathType: Prefix + EOF + environment: + KUBECONFIG: /etc/kubernetes/admin.conf + PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + when: true + +- name: Workaround for binder socket and bind-mount race-condition + hosts: nfs, ingress, worker, gpu + become: true + tasks: + - name: Binder socket cleaner - dind + copy: + src: files/etc/cron.d/binder-socket-cleaner-dind + dest: /etc/cron.d/binder-socket-cleaner-dind + mode: 0640 + - name: Binder socket cleaner - pink + copy: + src: files/etc/cron.d/binder-socket-cleaner-pink + dest: /etc/cron.d/binder-socket-cleaner-pink + mode: 0640 diff --git a/egi-devel/playbooks/files/egi-binder-logo.svg b/egi-devel/playbooks/files/egi-binder-logo.svg new file mode 120000 index 0000000000000000000000000000000000000000..7d79a06e2404fda95678afb0b21afe809297a0cd --- /dev/null +++ b/egi-devel/playbooks/files/egi-binder-logo.svg @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-binder-logo.svg \ No newline at end of file diff --git a/egi-devel/playbooks/files/egi-binder-page.html b/egi-devel/playbooks/files/egi-binder-page.html new file mode 120000 index 0000000000000000000000000000000000000000..5a3e4d627cdfe1d6b85ccea304b1df7709b13252 --- /dev/null +++ b/egi-devel/playbooks/files/egi-binder-page.html @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-binder-page.html \ No newline at end of file diff --git a/egi-devel/playbooks/files/egi-icon-replay.svg b/egi-devel/playbooks/files/egi-icon-replay.svg new file mode 120000 index 0000000000000000000000000000000000000000..d5846bef267e33e92ed1e9ffff751ffc70d7f67e --- /dev/null +++ b/egi-devel/playbooks/files/egi-icon-replay.svg @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-icon-replay.svg \ No newline at end of file diff --git a/egi-devel/playbooks/files/egi-replay-privacy-policy.html b/egi-devel/playbooks/files/egi-replay-privacy-policy.html new file mode 120000 index 0000000000000000000000000000000000000000..69e28ae7016a87c077eb597096e20263124403d3 --- /dev/null +++ b/egi-devel/playbooks/files/egi-replay-privacy-policy.html @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-replay-privacy-policy.html \ No newline at end of file diff --git a/egi-devel/playbooks/files/egi-replay-terms-of-use.html b/egi-devel/playbooks/files/egi-replay-terms-of-use.html new file mode 120000 index 0000000000000000000000000000000000000000..815938f9069250760700fc747f6b95ba7b955012 --- /dev/null +++ b/egi-devel/playbooks/files/egi-replay-terms-of-use.html @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-replay-terms-of-use.html \ No newline at end of file diff --git a/egi-devel/playbooks/files/egi-style.css b/egi-devel/playbooks/files/egi-style.css new file mode 120000 index 0000000000000000000000000000000000000000..b8f15e8edfa5a4514f144d9f5a44c2fe92153465 --- /dev/null +++ b/egi-devel/playbooks/files/egi-style.css @@ -0,0 +1 @@ +../../../common/playbooks/files/egi-style.css \ No newline at end of file diff --git a/egi-devel/playbooks/templates/binder.yaml b/egi-devel/playbooks/templates/binder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46cbefdd0848b0ee0dd3cceb7e3441f365bf791b --- /dev/null +++ b/egi-devel/playbooks/templates/binder.yaml @@ -0,0 +1,240 @@ +--- +# Secrets in "/nexus": +# +# * binder: user password for Jupyter Binder +# +# (also the "binder" user must exist in Nexus, see templates/nexus/user-*.yaml) +# + +config: + BinderHub: + auth_enabled: true + hub_url: "https://{{ binder_hostname }}/hub" + use_registry: true + image_prefix: {{ registry_binder_hostname }}/{{site_name}}/binder- + # build_image: quay.io/jupyterhub/repo2docker:2024.07.0 + build_token_secret: "{{ secrets['build_token_secret'] }}" + +extraVolumes: + - name: egi-binder-templates + configMap: + name: egi-binder-templates + - name: egi-binder-static + configMap: + name: egi-binder-static + +extraVolumeMounts: + - name: egi-binder-templates + mountPath: /etc/egi/templates + - name: egi-binder-static + mountPath: /etc/egi/static + +imageBuilderType: pink +# imageBuilderType: dind + +# dind: +# daemonset: +# extraArgs: +# - --mtu=1376 +# # share space with system docker volume +# hostLibDir: /var/lib/docker/dind + +pink: + daemonset: + image: + name: quay.io/podman/stable + tag: v5.4.1 + hostStorageDir: /var/lib/docker/pink-binder + hostSocketDir: /var/run/pink/binder + +ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + kubernetes.io/tls-acme: "true" + hosts: + - {{ binder_hostname }} + tls: + - hosts: + - {{ binder_hostname }} + secretName: acme-tls-binder + +service: + type: NodePort + +jupyterhub: + hub: + loadRoles: + user: + scopes: + - self + - "access:services!service=binder" + baseUrl: "/hub" + services: + binder: + admin: true + oauth_redirect_uri: "https://{{ binder_hostname }}/oauth_callback" + oauth_client_id: "service-binder" + oauth_no_confirm: true + image: + name: eginotebooks/hub + tag: "sha-aef23d2" + config: + Authenticator: + enable_auth_state: true + # keep in sync with cesnet/deployments/hub.yaml + allowed_groups: + - urn:mace:egi.eu:group:auger:role=member#aai.egi.eu + - urn:mace:egi.eu:group:biomed:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.cessda.eduteams.org:role=member#aai.egi.eu + - urn:mace:egi.eu:group:eiscat.se:Hub:role=member#aai.egi.eu + - urn:mace:egi.eu:group:eval.c-scale.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.environmental.egi.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.lethe-project.eu:lethe-notebooks:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.panosc.eu:role=vm_operator#aai.egi.eu + - urn:mace:egi.eu:group:vo.reliance-project.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.access.egi.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.notebooks.egi.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.bioexcel.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:group:vo.egu2024.egi.eu:role=member#aai.egi.eu + - urn:mace:egi.eu:www.egi.eu:fedcloud-users:member@egi.eu + - urn:mace:egi.eu:www.egi.eu:techsolutions:member@egi.eu + # changed 2022-10 + - urn:mace:egi.eu:group:fedcloud-users#sso.egi.eu + - urn:mace:egi.eu:group:supplier-notebooks#sso.egi.eu + - urn:mace:egi.eu:group:techsolutions#sso.egi.eu + - urn:mace:egi.eu:group:notebooks-support#sso.egi.eu + # changed 2025-03 + - urn:egi.eu:group:supplier-notebooks + - urn:egi.eu:group:notebooks-support + - urn:egi.eu:group:fedcloud-users + - urn:egi.eu:group:egi-ace-all + claim_groups_key: "eduperson_entitlement" + CryptKeeper: + keys: + - "ad1b7c99b6a00a853bb42448b5205a94d8064f1b0bb5486906b52be2fd4fe5f4" + EGICheckinAuthenticator: + checkin_host: "{{ secrets['checkin_host'] }}" + authorize_url: "https://{{ secrets['checkin_host'] }}/auth/realms/egi/protocol/openid-connect/auth" + token_url: "https://{{ secrets['checkin_host'] }}/auth/realms/egi/protocol/openid-connect/token" + userdata_url: "https://{{ secrets['checkin_host'] }}/auth/realms/egi/protocol/openid-connect/userinfo" + client_id: "{{ secrets['client_id'] }}" + client_secret: "{{ secrets['client_secret'] }}" + oauth_callback_url: "https://{{ binder_hostname }}/hub/oauth_callback" + scope: ["openid", "profile", "email", "offline_access", "eduperson_scoped_affiliation", "eduperson_entitlement"] + # username_key: "preferred_username" + username_key: "sub" + OnedataSpawner: + sidecar_image: "eginotebooks/oneclient-sidecar:sha-dd3068b" + force_direct_io: true + oneclient_extra_args: + - -o + - allow_other + http_timeout: 60 + JupyterHub: + admin_access: true + # redirect_to_server: false + authenticator_class: egi_notebooks_hub.egiauthenticator.EGICheckinAuthenticator + log_level: 'DEBUG' + # do not use EGI spawner for the binder here: + # spawner_class: egi_notebooks_hub.egispawner.EGISpawner + extraConfig: + 1-datahub: | + from egi_notebooks_hub.onedata import OnedataSpawner + class OnedataBinderSpawner(BinderSpawnerMixin, OnedataSpawner): + pass + c.JupyterHub.spawner_class = OnedataBinderSpawner + extraFiles: + login.html: + mountPath: /templates/login.html + stringData: |- + {% raw -%} + {% extends "egi-login.html" %} + + {% block nav_bar_right_items %} + <li> + <span id="user-guide"> + <a role="button" class="navbar-btn btn-sm btn btn-egi" href="https://docs.egi.eu/users/dev-env/replay/"> + <i aria-hidden="true" class="fa fa-book"></i> User Guide</a> + </span> + </li> + + {% endblock %} + + {% block main_intro %} + <h1> + <img alt="Replay Logo" src="{{ static_url('images/egi-icon-replay.svg') }}" height="100"> + Replay + </h1> + <p> + Replay offers an easy place to reproduce and share notebooks. + It allows users to replay complex calculations, simulations, and + visualisations scenarios by importing Notebooks and their runtime + environment and share them with a single link. Replay works well with + <a href="https://notebooks.egi.eu">EGI Notebooks</a>: + use-cases include workshops, scientific workflows and streamline sharing + among teams. + </p> + <p> + Access requires a valid <a href="https://docs.egi.eu/users/aai/check-in/signup/">EGI account</a> + and <a href="https://aai.egi.eu/registry/co_petitions/start/coef:111">enrolling + to the vo.notebooks.egi.eu VO</a>. + </p> + <p> + Default environment provides up to 4 CPU cores and 6 GB RAM per user. + </p> + {% endblock main_intro %} + {% block main_outro %} + <p> + Replay is based on <a href="https://jupyter.org/binder">Jupyter Binder</a> and runs on + the <a href="https://www.egi.eu/services/cloud-compute/">EGI cloud service</a>. You + can learn more at our <a href="https://docs.egi.eu/users/dev-env/binder/">documentation</a>. + </p> + <p> + This Replay instance is operated by and uses resources from + <a href="https://www.cesnet.cz/?lang=en">CESNET</a>. + User communities/advanced users can have their customised Binder + instance. EGI offers consultancy and support, as well as can operate the setup. + Email support _at_ egi.eu to request a community instance. + </p> + {% endblock main_outro %} + {%- endraw %} + + egi-icon-replay.svg: + mountPath: /usr/local/share/jupyterhub/static/images/egi-icon-replay.svg + stringData: |- + {{ lookup('file', 'files/egi-icon-replay.svg') | indent(width=10) }} + + templatePaths: + - /templates + - /egi-notebooks-hub/templates + templateVars: + service_name: "Replay" + ingress: + enabled: true + annotations: + kubernetes.io/ingress.class: "nginx" + kubernetes.io/tls-acme: "true" + hosts: + - {{ binder_hostname }} + tls: + - hosts: + - {{ binder_hostname }} + secretName: acme-tls-binder + proxy: + service: + type: NodePort + singleuser: + # to make notebook servers aware of hub (needed for user token refresh) + cmd: jupyterhub-singleuser + cull: + timeout: 7200 + every: 300 + debug: + enabled: true + +registry: + url: "https://{{ registry_binder_hostname }}" + # keep in sync with playbooks/templates/nexus/user-*.yaml + username: binder + password: "{{ nexus_secrets['binder'] }}"