diff --git a/.readthedocs.yml b/.readthedocs.yml index 19536a3..560ec3c 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,18 +4,17 @@ version: 2 build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: python: "3.12" nodejs: "16" - -sphinx: - configuration: conf.py - builder: dirhtml + commands: + - pip install -r requirements.txt + - cd scripts; python feature-table.py # Generate the feature table in about/distributions/index.md + - cd scripts; python download-figures.py # Download figures not in the GH repo + - jupyter-book build --builder dirhtml . + - mkdir -p $READTHEDOCS_OUTPUT/html/ + - cp -r _build/dirhtml/* $READTHEDOCS_OUTPUT/html/ # Explicitly opt out of trying to build additional formats such as PDF and ePub -formats: [] - -python: - install: - - requirements: requirements.txt +formats: [] \ No newline at end of file diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..8104578 --- /dev/null +++ b/_config.yml @@ -0,0 +1,113 @@ +####################################################################################### +# A default configuration that will be loaded for all jupyter books +# Users are expected to override these values in their own `_config.yml` file. +# This is also the "master list" of all allowed keys and values. + +####################################################################################### +# Book settings +title : Hub Service Guide # The title of the book. Will be placed in the left navbar. +author : 2i2c # The author of the book +copyright : "2024" # Copyright year to be placed in the footer +version : "0.1" +logo : "" # A path to the book logo +# Patterns to skip when building the book. Can be glob-style (e.g. "*skip.ipynb") +exclude_patterns : [_build, Thumbs.db, .DS_Store, README.md, .github, .nox, CONTRIBUTING.md, "**.ipynb_checkpoints"] +# Auto-exclude files not in the toc +only_build_toc_files : false + +####################################################################################### +# Parse and render settings +parse: + myst_enable_extensions: # default extensions to enable in the myst parser. See https://myst-parser.readthedocs.io/en/latest/using/syntax-optional.html + # - amsmath + - colon_fence + - deflist + - dollarmath + # - html_admonition + # - html_image + - linkify + # - replacements + # - smartquotes + - substitution + - tasklist + myst_url_schemes: [mailto, http, https] # URI schemes that will be recognised as external URLs in Markdown links + myst_dmath_double_inline: true # Allow display math ($$) within an inline context + +####################################################################################### +# HTML-specific settings +html: + favicon : "images/favicon.ico" # A path to a favicon image + use_edit_page_button : false # Whether to add an "edit this page" button to pages. If `true`, repository information in repository: must be filled in + use_repository_button : true # Whether to add a link to your repository button + use_issues_button : false # Whether to add an "open an issue" button + use_multitoc_numbering : true # Continuous numbering across parts/chapters + extra_footer : "" # Will be displayed underneath the footer. + google_analytics_id : "" # A GA id that can be used to track book views. + home_page_in_navbar : false # Whether to include your home page in the left Navigation Bar + baseurl : "https://docs.2i2c.org/" # The base URL where your book will be hosted. Used for creating image previews and social links. e.g.: https://mypage.com/mybook/ + analytics: + + comments: + hypothesis : false + utterances : false + announcement : "" # A banner announcement at the top of the site. + +####################################################################################### +# LaTeX-specific settings +latex: + latex_engine : pdflatex # one of 'pdflatex', 'xelatex' (recommended for unicode), 'luatex', 'platex', 'uplatex' + use_jupyterbook_latex : true # use sphinx-jupyterbook-latex for pdf builds as default + +####################################################################################### +# Launch button settings +launch_buttons: + notebook_interface : classic # The interface interactive links will activate ["classic", "jupyterlab"] + binderhub_url : "" # The URL of the BinderHub (e.g., https://mybinder.org) + jupyterhub_url : "" # The URL of the JupyterHub (e.g., https://datahub.berkeley.edu) + thebe : false # Add a thebe button to pages (requires the repository to run on Binder) + colab_url : "" # The URL of Google Colab (https://colab.research.google.com) + +repository: + url : https://github.com/2i2c-org/docs # The URL to your book's repository + path_to_book : "" # A path to your book's folder, relative to the repository root. + branch : main # Which branch of the repository should be used when creating links + +####################################################################################### +# Advanced and power-user settings +sphinx: + extra_extensions : # A list of extra extensions to load by Sphinx (added to those already used by JB). + - myst_nb + - sphinx_copybutton + - sphinx_design + - sphinx.ext.intersphinx + - sphinxext.rediraffe + local_extensions : # A list of local extensions to load by sphinx specified by "name: path" items + recursive_update : false # A boolean indicating whether to overwrite the Sphinx config (true) or recursively update (false) + config : # key-value pairs to directly over-ride the Sphinx configuration + html_theme : sphinx_2i2c_theme + intersphinx_mapping : + tc: + - 'https://team-compass.2i2c.org' + - null + infra: + - 'https://infrastructure.2i2c.org' + - null + jb: + - 'https://jupyterbook.org/en/stable' + - null + z2jh: + - 'https://z2jh.jupyter.org/en/latest' + - null + intersphinx_disabled_reftypes : ["*"] # prevent local references from resolving to external docs + rediraffe_branch : main + rediraffe_redirects : + # Added around 2022-09 + about/overview.md: about/service/index.md + about/pricing/index.md: about/service/options.md + # Added 2022-11-29 + about/service/roles.md: about/service/shared-responsibility.md + about/service/team.md: about/service/shared-responsibility.md + linkcheck_ignore : + - "https://openstoragenetwork.org*" # It incorrectly fails with `Max retries exceeded with url` + - "https://docs.github.com*" # Because docs.github.com returns 403 Forbidden errors + linkcheck_anchors : false diff --git a/_static/custom.js b/_static/custom.js new file mode 100644 index 0000000..53d3d1d --- /dev/null +++ b/_static/custom.js @@ -0,0 +1,15 @@ +/* This is the function to open the widget code */ +function openWidget() { +FreshworksWidget('open'); +} + +/* This is the widget embed code */ +window.fwSettings = { +'widget_id':80000009162 +}; +!function(){if("function"!=typeof window.FreshworksWidget){var n=function(){n.q.push(arguments)};n.q=[],window.FreshworksWidget=n}}() + +/* This is copied from https://euc-widget.freshworks.com/widgets/80000009162.js */ +window.onload = function() { /* Wait for document.body to be available */ + var FwBootstrap=function(e){var t={};function s(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,s),i.l=!0,i.exports}return s.m=e,s.c=t,s.d=function(e,t,n){s.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},s.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,t){if(1&t&&(e=s(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(s.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)s.d(n,i,function(t){return e[t]}.bind(null,i));return n},s.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(t,"a",t),t},s.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},s.p="https://euc-widget.freshworks.com/widgetBase/",s(s.s=0)}([function(e,t,s){e.exports=s(2)},function(e,t){e.exports="https://euc-widget.freshworks.com/widgetBase/static/media/frame.d7ae132c.css"},function(e,t,s){"use strict";s.r(t);var n=["FrustrationTracking","Predictive"],i={boot:"queueComplete",open:"openWidget",close:"closeWidget",destroy:"destroyWidget",identify:"identifyFormFields",prefill:"prefillFormFields",clear:"clearFormFields",hide:"hideWidget",hideLauncher:"hideLauncher",showLauncher:"showLauncher",show:"showWidget",setLabels:"setLabels",updateSettings:"updateSettings",updatePreviewSettings:"updatePreviewSettings",updateTicketForms:"updateTicketForms",reloadComponents:"reloadComponents",authenticate:"authenticate",authenticateCallback:"authenticateCallback",logout:"logout",hideFormFields:"hideFormFields",disable:null,disableFormFields:"disableFormFields",hideChoices:"hideChoices"},o={id:1,product_id:1,account_id:1,name:"Help widget",settings:{message:"",button_text:"Help",contact_form:{form_type:2,form_title:"",form_button_text:"Send",form_submit_message:"Thank you for your feedback.",attach_file:!0,screenshot:!0,captcha:!1},appearance:{position:1,offset_from_right:30,offset_from_left:30,offset_from_bottom:30,theme_color:"#2392ec",button_color:"#16193e"},components:{contact_form:!0,solution_articles:!0},predictive_support:{welcome_message:"",message:"We noticed you’re stuck. Tell us what you were trying to accomplish, and our support team will reach out to you as soon as possible.",success_message:"Thanks. We'll be in touch!",domain_list:["freshpo.com"]},hide_launcher_bydefault:!0},active:!0,updated_at:"2018-10-01T14:16:05+05:30",account_url:"https://localhost.freshdesk-dev.com",recaptcha_enterprise:!1,languages:{primary:"en",supported:["ca","cs","da","de","es-LA","es","et","fi","fr","hu","id","it","ja-JP","ko","nb-NO","nl","pl","pt-BR","pt-PT","ru-RU","sv-SE","sk","sl","tr","vi","zh-CN","uk","th","ro","zh-TW","lv-LV","bs","bg","hr","el","ms","lt","sr"]}};function r(){return window.fwSettings&&window.fwSettings.preview}function a(e,t){return e.indexOf(t)>=0}var d={init:function(){var e=window.fwSettings.widget_id;if(e)if(this.origin=window.location.origin,r()){var t=o;t.id=e,this.initWidget(t,!0)}else{var s="".concat("https://euc-widget.freshworks.com","/widgets/").concat(e,".json?randomId=").concat(Math.random());this.fetchSettings(s,this.initWidget.bind(this))}},fetchSettings:function(e,t){var s=new XMLHttpRequest;s.onreadystatechange=function(){4===s.readyState&&200===s.status&&t(function(e){try{return JSON.parse(e)}catch(t){return e}}(s.response))},s.open("get",e),s.responseType="json",s.send()},showWidget:function(e){var t=!1,s=e.meta,n=e.settings,i=e.components;return(i||n.components)&&["contact_form","solution_articles","frustration_tracking","predictive_support"].forEach(function(e){var o=s&&s.data_version&&i?i[e]&&i[e].enabled:n.components[e];t=t||Boolean(o)}),t},initWidget:function(e){var t,s=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null!=(t=e)&&0!==Object.keys(t).length&&e&&this.showWidget(e)){this.options=e,window.fwSettings.originUrl=this.origin;var n=new URL(e.account_url).hostname;if(!s&&!/.*(\.freshdesk.com|\.freshpo.com)$/.test(n))return;window.fwSettings.options=e,this.messageHandler=this.handleMessage.bind(this),this.createMountPoint(),this.loadIFrame(),this.loadJS()}},createMountPoint:function(){var e=document.createElement("div");e.id="freshworks-container",e.style.width="0px",e.style.height="0px",e.style.bottom="0px",e.style.right="0px",e.style.zIndex=Number.MAX_SAFE_INTEGER,e.setAttribute("data-html2canvas-ignore",!0),document.body.appendChild(e);var t=s(1),n=document.createElement("link");n.id="freshworks-frame",n.rel="stylesheet",n.href=t,document.head.appendChild(n)},loadIFrame:function(){var e=document.createElement("iframe");e.setAttribute("title","FreshworksWidget"),e.setAttribute("id","freshworks-frame"),e.setAttribute("data-html2canvas-ignore",!0),e.style.display="none",e.onload=function(){var t=document.createElement("link");t.setAttribute("rel","preconnect"),t.setAttribute("href","https://euc-widget.freshworks.com/widgetBase"),e.contentDocument.head.appendChild(t)},document.body.appendChild(e),this._frame=e;var t=e.contentDocument||e.document;t.open(),t.close();var s=document.createElement("script");s.setAttribute("src","".concat("https://euc-widget.freshworks.com/widgetBase","/widget.js")),s.setAttribute("async",!0),s.setAttribute("defer",!0),t.head.appendChild(s),this.bindMessageHandler()},loadJS:function(){if(this.isFrustrationTrackingEnabled()){var e=this.frustrationTrackingData();if(e&&!window.FM&&!r()){var t=document.createElement("script");t.src="".concat("https://cdn.freshmarketer.com","/").concat(e.org_id,"/").concat(e.project_id,".js"),t.async=!0,document.body.appendChild(t)}}},helpWidgetMethods:function(e,t,s,n){if(e&&d[e]&&a(Object.keys(i),e))return d[e](t,s,n)},widgetRenderComplete:function(){if(document.body.contains(this._frame)){var e=window.FreshworksWidget&&window.FreshworksWidget.q||[];window.FreshworksWidget=this.helpWidgetMethods,e.forEach(function(e){window.FreshworksWidget.apply(null,e)}),this.postMessage(i.boot)}},bindMessageHandler:function(){this.postMessageHandlerBound||(this.postMessageHandlerBound=!0,window.addEventListener?window.addEventListener("message",this.messageHandler,!0):window.attachEvent("message",this.messageHandler,!0))},unbindMessageHandler:function(){this.postMessageHandlerBound&&(this.postMessageHandlerBound=!1,window.removeEventListener?window.removeEventListener("message",this.messageHandler,!0):window.detachEvent("message",this.messageHandler,!0))},handleMessage:function(e){if(e.origin===this.origin||"file://"===this.origin){var t=e.data,s=t.eventName,n=t.data;(s||"function"==typeof this[s])&&this[s](n)}},postMessage:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};this._frame.contentWindow.postMessage({eventName:e,data:t},a(this.origin,"file://")?null:this.origin)},boot:function(){this.bindMessageHandler(),this._frame.contentWindow.Widget.mount(this.origin),this.postMessage(i.boot)},isFrustrationTrackingEnabled:function(){var e=this.options,t=e.meta,s=e.settings,n=e.components;return t&&t.data_version&&n?n.frustration_tracking&&Boolean(n.frustration_tracking.enabled):Boolean(s.components.predictive_support)},frustrationTrackingData:function(){var e=this.options,t=e.meta,s=e.settings,n=e.freshmarketer;return t&&t.data_version?n:s.freshmarketer},open:function(e,t){var s=(e||{}).widgetType;if(e&&s&&a(n,s)){if(!this.isFrustrationTrackingEnabled()&&!r())return;this._frame.contentWindow.Widget.el||this._frame.contentWindow.Widget.mount(this.origin,e.widgetType)}this.postMessage(i.open,{cardType:e,data:t})},close:function(){this.postMessage(i.close)},prefill:function(e,t,s){this.postMessage(i.prefill,{formName:e,formFields:t,options:s})},identify:function(e,t){this.postMessage(i.identify,{formName:e,formFields:t})},disable:function(e,t,s){this.postMessage(i.disableFormFields,{formName:e,formFields:t,options:s})},clear:function(e,t){this.postMessage(i.clear,{formName:e,options:t})},hide:function(e,t,s){e?t?this.postMessage(i.hideFormFields,{formName:e,formFields:t,options:s}):"launcher"===e&&this.postMessage(i.hideLauncher):this.postMessage(i.hide)},show:function(e){"launcher"===e?this.postMessage(i.showLauncher):this.postMessage(i.show)},hideChoices:function(e,t,s){this.postMessage(i.hideChoices,{formName:e,formFieldsAndChoices:t,options:s})},setLabels:function(e){this.postMessage(i.setLabels,e)},updateSettings:function(e){this.postMessage(i.updateSettings,e)},updatePreviewSettings:function(e){this.postMessage(i.updatePreviewSettings,e)},updateTicketForms:function(e){this.postMessage(i.updateTicketForms,e)},reloadComponents:function(){this.postMessage(i.reloadComponents)},destroy:function(){this._frame.contentWindow.Widget.unmount(),this.unbindMessageHandler()},authenticate:function(e){var t=e.callback,s=e.token,n=t&&"function"==typeof t,o="function"==typeof this.authenticateCallback,r=n||o;n&&(this.authenticateCallback=t),this.postMessage(i.authenticate,{token:s,hasCallback:r})},logout:function(){this.postMessage(i.logout)}};d.init()}]); +} \ No newline at end of file diff --git a/_toc.yml b/_toc.yml new file mode 100644 index 0000000..b84ce9b --- /dev/null +++ b/_toc.yml @@ -0,0 +1,20 @@ +root: index +entries: +- file: support +- file: about/terminology + entries: + - file: about/distributions/index + entries: + - file: about/distributions/education + - file: about/distributions/research + - file: about/service/index + entries: + - file: about/service/comparison + - file: about/service/options + - file: about/service/service-objectives + - file: about/service/shared-responsibility +- file: community/content + entries: + - file: community/events + - file: community/strategy +- file: topic/cloud-costs \ No newline at end of file diff --git a/about/distributions/index.md b/about/distributions/index.md index 0f8c1b4..682c557 100644 --- a/about/distributions/index.md +++ b/about/distributions/index.md @@ -3,7 +3,7 @@ 2i2c builds and operates **distributions of JupyterHubs** that are tailored for particular use-cases. These services share many of the same infrastructure components, but have customizations and optimizations that are more domain- or community-specific. -```{figure} https://drive.google.com/uc?export=download&id=1vL8ekAtUQ4TEik4-oWIn36VAOITdlmpR +```{figure} ../../images/hub-overview.png :width: 80% A high-level technical overview of an Interactive Computing Service collaboratively run by 2i2c and a community of practice. Each hub is a JupyterHub Distribution with a collection of community-led open source projects that are customized for a particular use-case. @@ -69,7 +69,7 @@ Your 2i2c JupyterHub has an environment that has been created for your particula All of the configuration and deployment scripts for the 2i2c JupyterHub can be found at [the `infrastructure/` repository](https://github.com/2i2c-org/infrastructure). This repository contains both the deployment code as well as documentation that explains how it works. It should be treated as "for advanced users only", and is provided for transparency and as a guide for the community to follow if they wish to manage their own infrastructure similar to 2i2c JupyterHub. -To learn about how the `infrastructure/` repository works, we recommend checking out the [`infrastructure` documentation](infra:index). +To learn about how the `infrastructure/` repository works, we recommend checking out the {doc}`Infrastructure documentation `. See the next sections for more information about each hub distribution. @@ -86,7 +86,7 @@ As members of the JupyterHub team, we are constantly looking for ways to improve 2i2c will not collect user data for any purpose beyond what is required in order to run a JupyterHub. Depending on the choices of your community the hub might contain identifiable information (e.g., e-mail addresses used as usernames for authentication), but this will remain within your hub's configuration and is not shared publicly. -Our {role}`Site Reliability Engineer`s will have access to all of the information that is inside a hub (which it requires in order to debug problems and and assist with upgrades), however we will not retain any of this data or move it *outside* of the hub, and will not retain it once the hub is shut down (except in order to transfer data to you at your request). +Our {ref}`Site Reliability Engineer`s will have access to all of the information that is inside a hub (which it requires in order to debug problems and and assist with upgrades), however we will not retain any of this data or move it *outside* of the hub, and will not retain it once the hub is shut down (except in order to transfer data to you at your request). ## Monitored for abuse and unexpected costs diff --git a/about/service/comparison.md b/about/service/comparison.md index 6272e97..4abf0f4 100644 --- a/about/service/comparison.md +++ b/about/service/comparison.md @@ -59,7 +59,7 @@ We strive to build an understanding of their needs, to represent their interests 2i2c is a mission-driven non-profit organization that has a commitment to doing its work openly, transparently, and inclusively. Our mission is to provide researchers and educators with the infrastructure they need to do their work, and to support open source communities that underlie this infrastructure. -2i2c is governed by a [Steering Council](tc:structure:steerco) made of members from the research and education community. +2i2c is governed by a {doc}`Steering Council ` made of members from the research and education community. 2i2c manages all of our work in public spaces, including [all of our infrastructure](http://github.com/2i2c-org/infrastructure) as well as [all of our organizational strategy and practices](http://team-compass.2i2c.org/). @@ -475,7 +475,7 @@ Updates There are many companies offering services and platforms via a subscription fee. The experience from a user's perspective may be similar and they may offer some open source tools as part of their services. -Examples of these products are [CoCalc](https://cocalc.com/), [Deepnote](https://deepnote.com/), [engageLively](https://engagelively.com/), [Colaboratory (Google)](https://colab.research.google.com/), [Noteable](https://noteable.io/), [ObserveableHQ](https://observablehq.com/), [rstudio.cloud](https://rstudio.cloud/), [Sagemaker (AWS)](https://aws.amazon.com/sagemaker/), and [Saturn Cloud](https://saturncloud.io/). +Examples of these products are [CoCalc](https://cocalc.com/), [Deepnote](https://deepnote.com/), [engageLively](https://galyleo.engagelively.com/), [Colaboratory (Google)](https://colab.research.google.com/), [ObserveableHQ](https://observablehq.com/), [rstudio.cloud](https://rstudio.cloud/), [Sagemaker (AWS)](https://aws.amazon.com/sagemaker/), and [Saturn Cloud](https://saturncloud.io/). Usage cost : Generally charge betwee $7 and $50 per user, per month, depending on the complexity of the resources needed and the service. Many SaaS offerings include enterprise services as well, but their prices are generally not advertised publicly and are often significantly more expensive. diff --git a/about/service/service-objectives.md b/about/service/service-objectives.md index f541f5b..4ef7413 100644 --- a/about/service/service-objectives.md +++ b/about/service/service-objectives.md @@ -79,14 +79,14 @@ Below are our objectives broken down by the type of support they relate to. :::{seealso} - See [](../../support.md) for more information about contacting support. -- See [](tc:support:process) for our team's support process. +- See {doc}`our Team Support Process` for our team's support process. ::: ### General support objectives - We have a dedicated communications channel for support (see [](../../support.md)). - At least one team member is always tasked with monitoring this channel. -- Our support team is communicative, helpful, and [abides by our Code of Conduct](tc:code-of-conduct). +- Our support team is communicative, helpful, and abides by our {ref}`Code of Conduct`. ### Incident support objectives diff --git a/about/service/shared-responsibility.md b/about/service/shared-responsibility.md index b0c71c5..075bc63 100644 --- a/about/service/shared-responsibility.md +++ b/about/service/shared-responsibility.md @@ -1,5 +1,3 @@ -```{team} Service Team -``` # Shared responsibility model 2i2c **shares responsibility for each hub** with the communities we serve.[^similar-models] @@ -39,11 +37,9 @@ Below we describe these areas in more detail, and define the roles that 2i2c and 4. **Enhance and develop cloud infrastructure**. Continuously develop and deploy software improvements with the goal of boosting service reliability and scalability. 5. **Operate a Kubernetes cluster**. This is the cloud platform that manages all of a community's infrastructure, and may be shared between many communities. -```{role} Site Reliability Engineer -``` - +(role:site-reliability-engineer)= ```{admonition} Role: Site Reliability Engineer -A team of engineers with expertise in cloud infrastructure and open source tools that we use as part of our services. This group of people oversees the cloud infrastructure that a community uses. They perform new development and upgrades, make changes per the request of {team}`Community Representatives`, and coordinate with the {team}`Community Support Team` during incidents and outages. +A team of engineers with expertise in cloud infrastructure and open source tools that we use as part of our services. This group of people oversees the cloud infrastructure that a community uses. They perform new development and upgrades, make changes per the request of {ref}`Community Representative`s, and coordinate with the [Support Process](../../support.md) during incidents and outages. This is roughly equivalent to a [Site Reliability Engineering Team](https://en.wikipedia.org/wiki/Site_reliability_engineering). See [our Infrastructure documentation](https://infrastructure.2i2c.org/en/latest/) for more information. @@ -67,12 +63,11 @@ Usually, 2i2c assumes responsibility for all of the above, though we are experim 4. **Create and manage data in the cloud**. If your communities requires access to a cloud-native dataset, format it properly and put it in a place that the hub can connect to. 5. **Run workshops and training**. Training workshops are geared towards community leaders, with the goal of helping them share knowledge with others in their community. -```{role} Community Guide -``` +(role:community-guide)= ```{admonition} Role: Community Guide An expert practitioner with familiarity in user workflows as well as the technical use-cases that 2i2c's cloud services enable. -Acts as a bridge between the communities we work with and our {role}`Site Reliability Engineer`s. Facilitates information transfer, signal-boosts community needs and requests, and guides communities in utilizing the infrastructure more effectively. +Acts as a bridge between the communities we work with and our {ref}`Site Reliability Engineer`s. Facilitates information transfer, signal-boosts community needs and requests, and guides communities in utilizing the infrastructure more effectively. See the {ref}`Support Team Documentation ` for more information. @@ -91,30 +86,28 @@ However, our base service model does not allow us to spend extensive time managi ### Responsibilities -A team of leaders *within the community that we work with* who act as {team}`Community Representatives` on behalf of their community. This team coordinates more closely with our {team}`Community Support Team`, facilitates the transfer of knowledge between 2i2c teams and communities of users, and helps manage the structure and dynamics of these communities. They also define the strategic mission and goals of each user community, and help us define the definition of "success" for the hub service. +A team of leaders *within the community that we work with* who act as {ref}`Community Representatives` on behalf of their community. This team coordinates more closely with our [Support Process](../../support.md), facilitates the transfer of knowledge between 2i2c teams and communities of users, and helps manage the structure and dynamics of these communities. They also define the strategic mission and goals of each user community, and help us define the definition of "success" for the hub service. 1. **Define success for the hub's community**. Community leaders understand the goals of a community's users, and define whether the hub is meeting their needs. 2. **Oversee user access policy**. Decide who has access to the hub, and what permissions they have. Generally done via the JupterHub admin panel. 3. **Manage and cultivate a community around the hub.** Define the community events, processes, structure, and communication channels that are best for a hub's community. -4. **Represent community in decisions and feedback**. Serve as a point of contact for {role}`Site Reliability Engineer`s, make requests for changes to the hub, and surface incidents or problems if they arise. +4. **Represent community in decisions and feedback**. Serve as a point of contact for {ref}`Site Reliability Engineer`s, make requests for changes to the hub, and surface incidents or problems if they arise. 5. **Make financial decisions about the hub**. Have decision authority for changes that have a financial impact on the infrastructure, and serve as a point of contact for billing matters. -```{role} Hub Administrator -``` +(role:hub-administrator)= ```{admonition} Role: Hub Administrator Trusted community members that perform common administrative operations on a hub that do not require intervention from a Hub Engineer. -{team}`Community Representatives` are the first Hub Administrators, and they may add new Hub Administrators via the JupyterHub interface. +{ref}`Community Representatives` are the first Hub Administrators, and they may add new Hub Administrators via the JupyterHub interface. They are able to add users, start/stop servers, and generally have more control over operations on the hub. **Filled by a community member**. ``` -```{role} Community Representative -``` +(role:community-representative)= ```{admonition} Role: Community Representative -Acts as the primary point of contact for a community, and ensures that the interests of the {team}`Hub Community` are represented in the infrastructure, and that the hub serves their needs. +Acts as the primary point of contact for a community, and ensures that the interests of the Hub Community are represented in the infrastructure, and that the hub serves their needs. They have the authority to speak on behalf of the community, and make decisions about the infrastructure that the community uses. diff --git a/admin/howto/control-user-server.md b/admin/howto/control-user-server.md index 4c1b005..e78a764 100644 --- a/admin/howto/control-user-server.md +++ b/admin/howto/control-user-server.md @@ -29,7 +29,9 @@ Accessing a user's server is useful when trying to debug or reproduce an issue t If you both work on the same notebook at the same time, you will just overwrite each other's code! The state of the notebook will be that of whoever saved the notebook last. There is no Google Docs' style - real-time collaboration yet, although [it is coming](https://github.com/jupyterlab/rtc) + real-time collaboration available on our hubs yet, although + you can refer to the [Jupyter Real-Time Collaboration extension](https://jupyterlab-realtime-collaboration.readthedocs.io/) + for this feature. ::: :::{warning} @@ -111,7 +113,7 @@ By default, kernels will be checked for activity **every `5 minutes`**. All kernels that haven't shown activity in **in the last hour** will be stopped by the [jupyterhub-idle-culler](https://github.com/jupyterhub/jupyterhub-idle-culler). This window can be configured if you'd like to change the window of inactivity needed before user kernels will be stopped. -See the [Hub Engineer's guide](infra:configure:culling) for some documentation on this. +See the {doc}`Infrastructure Guide` for some documentation on this. % TODO: Add link to SRE guide on how to configure this, once it exists diff --git a/admin/howto/environment/index.md b/admin/howto/environment/index.md index 41b4351..21b5e4b 100644 --- a/admin/howto/environment/index.md +++ b/admin/howto/environment/index.md @@ -86,7 +86,7 @@ unable to start, due to conflicting packages. [See this blog post on using pip i ## Create multiple environments for users to select If your hub's community has workflows that differ significantly, it can be useful to create multiple user environments for your hub. -This uses [Jupyter Hub User Profiles](z2jh:multiple-profiles) to create a menu of environment options when a user launches a new session. +This uses to create a menu of environment options when a user launches a new session (see the [Zero to JupyterHub documentation](https://z2jh.jupyter.org/en/latest/jupyterhub/customizing/user-environment.html#using-multiple-profiles-to-let-users-select-their-environment)). To add multiple environments for your hub, take these steps: diff --git a/admin/howto/manage-users.md b/admin/howto/manage-users.md index 57fb00c..62d3418 100644 --- a/admin/howto/manage-users.md +++ b/admin/howto/manage-users.md @@ -2,7 +2,7 @@ ## Authentication vs. Authorization -- **Authentication** allows your users to prove who their are. +- **Authentication** allows your users to prove who they are. - **Authorization** gives users certain permissions depending on their identity (such as "access to your hub", or "administrative privileges"). (admin/configuration/authentication)= @@ -144,4 +144,4 @@ If users are running into strange errors when they log in (for example CILogon e 1. Try logging in with an `incognito` window. This will help determine if their issue is due to some cookie / cache that is stored on their machine. 2. Ask them to clear their cookies / cache for all CILogon websites. For example, [here are the Google Chrome instructions to clear cookies](https://support.google.com/chrome/answer/95647?hl=en&co=GENIE.Platform%3DDesktop). -3. If using `CILogon`, double-check that they've signed in with the correct account, and [ask them to switch accounts if needed](https://infrastructure.2i2c.org/en/latest/howto/configure/auth-management.html#switch-identity-providers-or-user-accounts). +3. If using `CILogon`, double-check that they've signed in with the correct account, and [ask them to switch accounts if needed](https://infrastructure.2i2c.org/howto/troubleshoot/cilogon-user-accounts/). diff --git a/admin/howto/replicate.md b/admin/howto/replicate.md index c9279de..6f6ae03 100644 --- a/admin/howto/replicate.md +++ b/admin/howto/replicate.md @@ -107,7 +107,7 @@ Below we'll cover how you can deploy your own JupyterHub using your 2i2c Jupyter 2i2c JupyterHubs use the [Zero to JupyterHub](https://z2jh.jupyter.org) guide for their configuration and deployments. We recommend familiarizing yourself with it, as it will be invaluable in helping you navigate how to run a JupyterHub that replicates the 2i2c JupyterHub service. -All of the configuration for a 2i2c JupyterHub exists at the [`infrastructure/` repository](infra:index). This is a "meta" repository that centralizes configuration and deployment of many 2i2c JupyterHubs. +All of the configuration for a 2i2c JupyterHub exists at the [2i2c-org/infrastructure](https://github.com/2i2c-org/infrastructure) repository. This is a "meta" repository that centralizes configuration and deployment of many 2i2c JupyterHubs. There are two main things you'll need from this repository to deploy your hub: diff --git a/community/content.md b/community/content.md index 0c7ad44..2b2affc 100644 --- a/community/content.md +++ b/community/content.md @@ -125,7 +125,7 @@ This way, your HTML files will automatically be updated when you update your sit Your hub will need to be configured by a 2i2c engineer to enable the docs service (following {doc}`these instructions `). - Find the **GitHub repository** and the **branch** where your HTML files are stored. -- [Send a support request](../../support.md) asking them to enable this, and provide the repository/branch you found above. +- Send a [Support Request](../support.md) asking them to enable this, and provide the repository/branch you found above. Once this is deployed, your hub's documentation should be accessible at @@ -133,7 +133,6 @@ Once this is deployed, your hub's documentation should be accessible at https:///services/docs ``` - ## Write public books that connect to a 2i2c JupyterHub You can create public content that is designed to connect with your @@ -144,8 +143,8 @@ Hub. To connect your public content with a 2i2c JupyterHub, we recommend using [Jupyter Book](https://jupyterbook.org). This is an open-source project that allows you to share collections of notebooks and markdown files as an online website and -book. Check out the [Jupyter Book getting started -guide](jb:start/overview) for more information about +book. Check out the {doc}`Jupyter Book Getting Started +Guide ` for more information about Jupyter Book. You can tell Jupyter Book to place links *directly to your 2i2c JupyterHub* on each diff --git a/conf.py b/conf.py index c6d6ac4..9dbfab7 100644 --- a/conf.py +++ b/conf.py @@ -1,9 +1,9 @@ # -- Project information ----------------------------------------------------- -project = "Service Guide" -copyright = "2022" +project = "Hub Service Guide" +copyright = "2024" author = "2i2c" -version = "0.1alpha" +version = "0.1" main_doc = "index" # -- General configuration --------------------------------------------------- @@ -54,8 +54,8 @@ } intersphinx_mapping = { - "tc": ('https://team-compass.2i2c.org/en/latest', None), - "infra": ('https://infrastructure.2i2c.org/en/latest', None), + "tc": ('https://team-compass.2i2c.org', None), + "infra": ('https://infrastructure.2i2c.org', None), "jb": ('https://jupyterbook.org/en/stable/', None), "z2jh": ('https://z2jh.jupyter.org/en/latest', None), } @@ -93,36 +93,9 @@ def setup(app): app.add_css_file("custom.css") - app.add_crossref_type("team", "team") - app.add_crossref_type("role", "role") # Add the JS code for our FreshDesk support widget # ref: https://support.freshdesk.com/en/support/solutions/articles/239273-setting-up-your-help-widget # ref: https://support.freshdesk.com/en/support/solutions/articles/50000001015-launching-the-widget-when-a-button-is-clicked app.add_js_file(None, body=widget_embed_code) app.add_js_file("https://euc-widget.freshworks.com/widgets/80000009162.js", **{"async": "", "defer": ""}) - -# -- Custom scripts ------------------------------------------------- - -# Generate the feature table -import subprocess -from pathlib import Path -build_assets = Path("build_assets") -build_assets.mkdir(exist_ok=True) -subprocess.run(["python", "feature-table.py"], cwd="scripts") - -# Download figures we keep in Google Drive -from requests import get -figures = { - "https://drive.google.com/uc?export=download&id=1Mr51-s3D_KHPsAuTXbczaQ7mlPZUs9gm": "collaborative_learning_hub.png", - "https://drive.google.com/uc?export=download&id=16r5xE7SguunLfMh5LhSynSUfjb7IXs_n": "shared_responsibility_diagram.png", - "https://drive.google.com/uc?export=download&id=1gWAIQVKcB-uxuJsBHqlDlRTq88oki1zn": "scalable_research_hub.png", -} -for url, filename in figures.items(): - path_image = Path(__file__).parent / "images" / filename - if not path_image.exists(): - print(f"Downloading {filename}...") - resp = get(url) - path_image.write_bytes(resp.content) - else: - print(f"Diagram image exists, delete this file to re-download: {path_image}") diff --git a/how-to-guides/add-packages-to-image.md b/how-to-guides/add-packages-to-image.md index 225db76..33e846e 100644 --- a/how-to-guides/add-packages-to-image.md +++ b/how-to-guides/add-packages-to-image.md @@ -3,7 +3,7 @@ This instructional guide shows you how to add packages to a community-maintained upstream image. In this example, we add the [Python package `xarray`](https://docs.xarray.dev/en/stable/) to the [`jupyter/scipy-notebook` image](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html) maintained by the [Jupyter Docker Stacks](https://jupyter-docker-stacks.readthedocs.io/en/latest/index.html) community. ```{contents} -:maxdepth: 2 +:depth: 2 :local: ``` @@ -35,7 +35,7 @@ The following summarizes [Section 3.2. Allowing robot access to a user repositor You can also edit permissions later by clicking {octicon}`gear;1em;sd-text-info` *Options* next to the Robot Account name and selecting *Set Repository Permissions*. ``` -1. Name your robot, e.g. `_image_builder` and then check the box next to the repository name that you created in [Set up GitHub repository and connect it to quay.io](#set-up-github-repository-and-connect-it-to-quay-io), e.g. `jupyter-scipy-xarray`. From the dropdown, select the *Write* permission and then confirm by clicking *Add permissions*. +1. Name your robot, e.g. `_image_builder` and then check the box next to the repository name that you created in {ref}`Set up GitHub repository and connect it to quay.io`, e.g. `jupyter-scipy-xarray`. From the dropdown, select the *Write* permission and then confirm by clicking *Add permissions*. 1. Click the Robot Account name to view its credentials, e.g. - *Username:* \+__image_builder @@ -83,10 +83,11 @@ Once complete, under the section *Repository secrets* you should now see two row 1. Click the ![Git icon](media/git.svg) Git icon in the left sidebar to open the JupyterLab Git extension. -1. Clone the forked repository from [Set up the GitHub repository and connect it to quay.io](#set-up-the-github-repository-and-connect-it-to-quay-io) into the hub by the clicking *Clone a Repository* button followed by entering the URL of the remote Git repository, e.g. `https://github.com//example-inherit-from-community-image.git`. +1. Clone the forked repository from {ref}`Set up GitHub repository and connect it to quay.io` into the hub by the clicking *Clone a Repository* button followed by entering the URL of the remote Git repository, e.g. `https://github.com//example-inherit-from-community-image.git`. 1. Change the working directory by double-clicking *example-inherit-from-community-image* in the file explorer on the left side of the screen. +(add-packages:build-base-image)= ### Build base image 1. Update the GitHub workflow files with your quay.io repository @@ -151,7 +152,7 @@ Once complete, under the section *Repository secrets* you should now see two row ### Trigger build and check the custom image on Binder -1. Stage, commit and push your changes by following the similar steps in Section [Build base image](build-base-image). +1. Stage, commit and push your changes by following the similar steps in Section {ref}`Build base image`. 1. Visit your GitHub repository at `https://github.com//example-inherit-from-community-image` and click the *Compare & pull request* button. @@ -185,8 +186,9 @@ Once complete, under the section *Repository secrets* you should now see two row //: ``` -e.g. `quay.io/jnywong/jupyter-scipy-xarray:739fec9705b1`, which you need to provide in the Section [Link custom image to your hub](#link-custom-image-to-your-hub). - +e.g. `quay.io/jnywong/jupyter-scipy-xarray:739fec9705b1`, which you need to provide in the Section {ref}`Link custom image to your hub`. + +(add-packages:link-custom-image)= ## Link custom image to your hub 1. Open a [2i2c support ticket](https://docs.2i2c.org/support/) to request an update to your hub with the new custom image. diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 0000000..76aef0d Binary files /dev/null and b/images/favicon.ico differ diff --git a/images/hub-overview.png b/images/hub-overview.png new file mode 100644 index 0000000..fa04c0d Binary files /dev/null and b/images/hub-overview.png differ diff --git a/images/logo.png b/images/logo.png index 95473c0..cd420f4 100644 Binary files a/images/logo.png and b/images/logo.png differ diff --git a/index.md b/index.md index 56c12ec..039c49d 100644 --- a/index.md +++ b/index.md @@ -1,4 +1,4 @@ -# Service Guide +# Hub Service Guide This is the community and user documentation for 2i2c's Managed JupyterHub Service. It is divided into a number of **roles and personas** with relevant topics for each. @@ -6,8 +6,8 @@ It is divided into a number of **roles and personas** with relevant topics for e :::{seealso} Here are a few other locations with relevant information about 2i2c's services. -- [`team-compass.2i2c.org/managed-hubs/index`](https://team-compass.2i2c.org/en/latest/projects/managed-hubs/index.html): Documentation about {team}`Service Team` processes that are primarily relevant to 2i2c team members. We put this documentation here to prevent [`docs.2i2c.org`](https://docs.2i2c.org) from getting too cluttered. -- [`infrastructure.2i2c.org`](https://infrastructure.2i2c.org): Our {team}`Cloud Engineering Team` and cloud infrastructure documentation. +- [`team-compass.2i2c.org/managed-hubs/index`](https://team-compass.2i2c.org/en/latest/projects/managed-hubs/index.html): Documentation about {doc}`Service Team` processes that are primarily relevant to 2i2c team members. We put this documentation here to prevent [`docs.2i2c.org`](https://docs.2i2c.org) from getting too cluttered. +- [`infrastructure.2i2c.org`](https://infrastructure.2i2c.org): Our {ref}`Cloud Engineering Team` and cloud infrastructure documentation. ::: This documentation is structured into sections that are meant for various **roles and personas**. diff --git a/noxfile.py b/noxfile.py index 52746ca..fe3667b 100644 --- a/noxfile.py +++ b/noxfile.py @@ -2,7 +2,8 @@ nox.options.reuse_existing_virtualenvs = True -build_command = ["-b", "dirhtml", ".", "_build/dirhtml"] +build_command = ["--builder", "dirhtml", "."] +sphinx_build_command = ["-b", "dirhtml", ".","_build/html"] @nox.session(python=">=3.9") def docs(session): @@ -16,7 +17,7 @@ def docs(session): cmd = ["sphinx-autobuild"] for folder in AUTOBUILD_IGNORE: cmd.extend(["--ignore", f"*/{folder}/*"]) - cmd.extend(build_command) + cmd.extend(sphinx_build_command) session.run(*cmd) else: - session.run("sphinx-build", *build_command) + session.run("jupyter-book", "build", *build_command) diff --git a/requirements.txt b/requirements.txt index 904f3c8..5199bba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,10 @@ myst-nb myst-parser[linkify] pandas +matplotlib pyyaml requests +jupyter-book sphinx sphinx-autobuild sphinx-copybutton diff --git a/scripts/download-figures.py b/scripts/download-figures.py new file mode 100644 index 0000000..b2f5e9c --- /dev/null +++ b/scripts/download-figures.py @@ -0,0 +1,17 @@ +# Download figures we keep in Google Drive. These figures are not version-controlled in the GH repo. + +from pathlib import Path +from requests import get +figures = { + "https://drive.google.com/uc?export=download&id=1Mr51-s3D_KHPsAuTXbczaQ7mlPZUs9gm": "collaborative_learning_hub.png", + "https://drive.google.com/uc?export=download&id=16r5xE7SguunLfMh5LhSynSUfjb7IXs_n": "shared_responsibility_diagram.png", + "https://drive.google.com/uc?export=download&id=1gWAIQVKcB-uxuJsBHqlDlRTq88oki1zn": "scalable_research_hub.png", +} +for url, filename in figures.items(): + path_image = Path("../images").joinpath(filename) + if not path_image.exists(): + print(f"Downloading {filename}...") + resp = get(url) + path_image.write_bytes(resp.content) + else: + print(f"Diagram image exists, delete this file to re-download: {path_image}") diff --git a/scripts/feature-table.py b/scripts/feature-table.py index f60e2ed..30792ba 100644 --- a/scripts/feature-table.py +++ b/scripts/feature-table.py @@ -25,9 +25,9 @@ import sys import pandas as pd - URL_FEATURE_MATRIX = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQ5p52Wu166vKpcjTu9jf5J2yNG6c_C2-pHRkNLGQwKN2gJ_1UoGlalaglsgtBfQ7W0-aTP11phpgSA/pub?gid=1864974850&single=true&output=csv" +Path("../build_assets").mkdir(exist_ok=True) path_csv = Path("../build_assets/feature-matrix.csv") if path_csv.exists(): print("Feature table exists, skipping update. Delete to re-generate it.") diff --git a/support.md b/support.md index c40f41f..3625508 100644 --- a/support.md +++ b/support.md @@ -10,7 +10,7 @@ When you make a support request, please include as much information as possible % Copy the style classes of sphinx-design buttons % The JavaScript that this calls is defined in conf.py ```{caution} @@ -20,7 +20,7 @@ Privacy extensions can block the pop-up contact form. ## Who can ask for support? -A {role}`Community Representative` of a hub should be the one that surfaces support requests to the 2i2c {role}`Site Reliability Engineer`ing team. +A {ref}`Community Representative` of a hub should be the one that surfaces support requests to the 2i2c {ref}`Site Reliability Engineering` team. Before reaching out to 2i2c for support, this person should work with others in their community to understand the problem and to ensure that it is something that requires intervention from a 2i2c Engineer. ## The support process diff --git a/topic/cloud-costs.md b/topic/cloud-costs.md index 14b4b53..e49f464 100644 --- a/topic/cloud-costs.md +++ b/topic/cloud-costs.md @@ -61,8 +61,8 @@ In practice, the cost per node depends heavily on the cloud provider, and is con We recommend checking out the following resources to learn more about cloud costs. None of these are guarantees about costs, but should give you a general idea. -- For general information and explanation, see [the Zero to JupyterHub cost projection documentation](z2jh:cost). -- For educational or "lightweight resources" hubs, see [this rough cost analysis notebook from the UC Berkeley DataHub](https://nbviewer.jupyter.org/github/berkeley-dsep-infra/datahub-usage-analysis/blob/master/notebooks/03-visualize-cost-and-usage.ipynb). +- For general information and explanation, see the {doc}`Zero to JupyterHub cost projection documentation`. +- For educational or "lightweight resources" hubs, see [this rough cost analysis notebook from the UC Berkeley DataHub](https://nbviewer.jupyter.org/github/berkeley-dsep-infra/datahub-usage-analysis/blob/main/notebooks/03-visualize-cost-and-usage.ipynb). - For data- and compute-intensive hubs, see the Pangeo two-part series on their Kubernetes costs. ([part 1 link](https://medium.com/pangeo/pangeo-cloud-costs-part1-f89842da411d), [part 2 link](https://medium.com/pangeo/pangeo-cloud-cluster-design-9d58a1bf1ad3)) ::: diff --git a/user/topics/policy/acceptable-use.md b/user/topics/policy/acceptable-use.md index ec37204..43cd958 100644 --- a/user/topics/policy/acceptable-use.md +++ b/user/topics/policy/acceptable-use.md @@ -25,7 +25,7 @@ When other policies are more restrictive than this policy, the more restrictive - You should make a reasonable effort to protect your passwords and to secure resources against unauthorized use or access. Where applicable you must configure access to other cloud services or data in a way that reasonably prevents unauthorized users from accessing them. - You must not attempt to access restricted portions of the network or any 2i2c Managed Infrastructure without appropriate authorization by a 2i2c engineer. -- You must not attempt to use 2i2c Managed Infrastructure for the purposes of [mining cryptocurrencies](https://en.wikipedia.org/wiki/Cryptocurrency#Mining) unless explicitly given permission by a {term}`Community Representative` for research purposes. +- You must not attempt to use 2i2c Managed Infrastructure for the purposes of [mining cryptocurrencies](https://en.wikipedia.org/wiki/Cryptocurrency#Mining) unless explicitly given permission by a {ref}`Community Representative` for research purposes. - You must not use 2i2c Managed Infrastructure and/or network resources in conjunction with the execution of programs, software, processes, or automated transaction-based commands that are intended to disrupt (or that could reasonably be expected to disrupt) other computer or network users, or damage or degrade performance, software or hardware components of a system. - Do not use the 2i2c Managed Infrastructure to distribute or facilitate the sending of unsolicited or unlawful (i) email or other messages, or (ii) promotions of any kind; - Do not use the 2i2c Managed Infrastructure to engage in or promote any other fraudulent, deceptive or illegal activities. diff --git a/user/topics/policy/privacy.md b/user/topics/policy/privacy.md index eeb21aa..b4e25ee 100644 --- a/user/topics/policy/privacy.md +++ b/user/topics/policy/privacy.md @@ -17,7 +17,7 @@ We require _access_ to the information our infrastructure while it is running, b - We do not retain or share this information for any purpose. - 2i2c may have access to personally-identifiable information that is used for _authenticating_ users (e.g. e-mail log-ins). - We do not retain or share this information for any purpose. -- We do not change or delete any user data on a hub without the consent of the hub's {term}`Community Representative`. +- We do not change or delete any user data on a hub without the consent of the hub's {ref}`Community Representative`. - We collect aggregate statistics about general _usage_ of the infrastructure for monitoring and alerting purposes (e.g., number of active users each hour). ## After we stop working with a community