ccp.docs/build/html/usermanual/index.html

629 lines
80 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html class="writer-html5" lang="en">
<head>
<meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>User manual &mdash; CCP 0.1.0 documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=80d5e7a1" />
<link rel="stylesheet" type="text/css" href="../_static/css/theme.css?v=19f00094" />
<link rel="canonical" href="/docs/usermanual/index.html" />
<!--[if lt IE 9]>
<script src="../_static/js/html5shiv.min.js"></script>
<![endif]-->
<script src="../_static/jquery.js?v=5d32c60e"></script>
<script src="../_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js?v=2389946f"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=4825356b"></script>
<script src="../_static/js/theme.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="prev" title="Introduction" href="../introduction.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="../index.html" class="icon icon-home">
CCP
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
<input type="text" name="q" placeholder="Search docs" aria-label="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../introduction.html">Introduction</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">User manual</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#infrastructures">Infrastructures</a></li>
<li class="toctree-l2"><a class="reference internal" href="#runtimes">Runtimes</a></li>
<li class="toctree-l2"><a class="reference internal" href="#methods">Methods</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#anatomy-of-a-method">Anatomy of a Method</a></li>
<li class="toctree-l3"><a class="reference internal" href="#lifecycle-of-a-method-execution">Lifecycle of a Method execution</a></li>
<li class="toctree-l3"><a class="reference internal" href="#execution-context-of-a-method">Execution context of a Method</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#executions">Executions</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#anatomy-of-an-execution">Anatomy of an Execution</a></li>
<li class="toctree-l3"><a class="reference internal" href="#method-and-execution-storage">Method and Execution storage</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#ui-widgets">UI Widgets</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#method-list">Method list</a></li>
<li class="toctree-l3"><a class="reference internal" href="#method-editor">Method editor</a></li>
<li class="toctree-l3"><a class="reference internal" href="#method-execution-form">Method execution form</a></li>
<li class="toctree-l3"><a class="reference internal" href="#execution-monitor">Execution monitor</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#rest-apis-interacting-with-methods-and-executions-programmatically">REST APIs: Interacting with Methods and Executions programmatically</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="../index.html">CCP</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="Page navigation">
<ul class="wy-breadcrumbs">
<li><a href="../index.html" class="icon icon-home" aria-label="Home"></a></li>
<li class="breadcrumb-item active">User manual</li>
<li class="wy-breadcrumbs-aside">
<a href="../_sources/usermanual/index.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<section id="user-manual">
<h1>User manual<a class="headerlink" href="#user-manual" title="Permalink to this heading"></a></h1>
<p>This manual documents the features of CCP (Cloud Computing Platform) available to scientists that want to design, integrate and execute their methods.</p>
<section id="infrastructures">
<h2>Infrastructures<a class="headerlink" href="#infrastructures" title="Permalink to this heading"></a></h2>
<p>Infrastructures are technological platforms on top of whom Methods are executed. They are identified by a unique id, a name, a description and a type.
The type defines also the encapsulation or containerisation technology used for the runtimes.
Currently CCP supports single Docker containers, Docker Swarm based clusters and LXD clusters.
It is responisibility of a Method developers to decide what infrastructure their Methods will be executed on and this restricts the type of Runtimes that can be selected.</p>
</section>
<section id="runtimes">
<h2>Runtimes<a class="headerlink" href="#runtimes" title="Permalink to this heading"></a></h2>
<p>Runtimes are containers that encapsulate a Method. They can be seen as minimal virtual environments made of an operating system and all dependencies required by a particular Method.
The technology and the list of available Runtimes is strictly related to type of the Infrastructure. In an Infrastructure of type Docker or Docker Swarm cluster the available Runtimes are listed in a registry of Docker containers for example.</p>
</section>
<section id="methods">
<h2>Methods<a class="headerlink" href="#methods" title="Permalink to this heading"></a></h2>
<p>Logically, Methods are computational functions or procedures. They can be implementations of algorithms or numerical recipes. data gatherings or transformations, AI modules, generation of visuals and charts. Whatever can be executed and produces a valuable scientific result that needs to be reproduceable and repeatable can be written as a Method.</p>
<p>CCP tries to be as lax as possible with respect to the technical constraints for Methods. It aims at supporting every language and every reasonable combination of operating systems and dependencies by providing stacks of Runtimes that provide many ready solutions but are simultaneously open to customisations.</p>
<section id="anatomy-of-a-method">
<h3>Anatomy of a Method<a class="headerlink" href="#anatomy-of-a-method" title="Permalink to this heading"></a></h3>
<p>At its heart a Method is a JSON structure that aggregates a section of metadata, the definition of input parameters, the description of expected outputs, instructions for customising the deploy and execute steps of its lifecycle and link to a compatible Infrastructure.</p>
<p>The syntax of the JSON data structure is constrained by the grammar proposed by the OGC Processes API specification (&lt;<a class="reference external" href="https://ogcapi.ogc.org/processes/">https://ogcapi.ogc.org/processes/</a>&gt;).</p>
<p>The following code snippet illustrates an example.</p>
<div class="highlight-json notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;408d9dc5-ee37-4123-9f07-4294f13bce19&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;JDK-8 Example maven&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Test for executing a jdk8 sample app from GitHub repository built with maven&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="s2">&quot;0.0.1&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;jobControlOptions&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="s2">&quot;async-execute&quot;</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;keywords&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="s2">&quot;jdk&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;java&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;jdk8&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;java8&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;maven&quot;</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Marco Lettere&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;author&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;https://accounts.dev.d4science.org/auth/admin/realms/d4science/users/88c76e47-5881-4716-a2bf-02d3b4073574&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;category&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Test&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;%2Fgcube%2Fdevsec%2FCCP&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;context&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;https://accounts.dev.d4science.org/auth/admin/realms/d4science/clients/%2Fgcube%2Fdevsec%2FCCP&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;outputTransmission&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="s2">&quot;value&quot;</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;inputs&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;ccpimage&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;ccpimage&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Runtime&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;The image of the runtime to use for method execution. This depends on the infrastructure specific protocol for interacting with registries.&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;format&quot;</span><span class="p">:</span><span class="s2">&quot;url&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;contentMediaType&quot;</span><span class="p">:</span><span class="s2">&quot;text/plain&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;default&quot;</span><span class="p">:</span><span class="s2">&quot;nubisware/ccp-jdk8-jammy:latest&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;readonly&quot;</span><span class="p">:</span><span class="s2">&quot;true&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;repository&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;repository&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Repository URL&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Git url to repository&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;format&quot;</span><span class="p">:</span><span class="s2">&quot;url&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;default&quot;</span><span class="p">:</span><span class="s2">&quot;https://github.com/dcore94/jdk-maven-example&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;mainclass&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;mainclass&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Main Class&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;The main class to run&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;default&quot;</span><span class="p">:</span><span class="s2">&quot;example.HelloWorld&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;outputs&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;filetext&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;filetext&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Text output&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Some output is written in txt format to file.txt&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;file.txt&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;file&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;/output/file.txt&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;contentMediaType&quot;</span><span class="p">:</span><span class="s2">&quot;text/plain&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;filexml&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;filexml&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;XML output&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Some output is written in XML format to file.xml&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;file.xml&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;file&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;/ccp_data/output/file.xml&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;contentMediaType&quot;</span><span class="p">:</span><span class="s2">&quot;application/xml&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;filejson&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;filejson&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;JSON output&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Some output is written in JSON format to file.json&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;file.json&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;file&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;/ccp_data/output/file.json&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;contentMediaType&quot;</span><span class="p">:</span><span class="s2">&quot;application/json&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;filecsv&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;id&quot;</span><span class="p">:</span><span class="s2">&quot;filecsv&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;CSV output&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="s2">&quot;Some output is written in CSV format to file.csv&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;minOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;maxOccurs&quot;</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;metadata&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;file.csv&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;role&quot;</span><span class="p">:</span><span class="s2">&quot;file&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;/output/file.csv&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">&quot;schema&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="s2">&quot;string&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;contentMediaType&quot;</span><span class="p">:</span><span class="s2">&quot;text/csv&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;additionalParameters&quot;</span><span class="p">:{</span>
<span class="w"> </span><span class="nt">&quot;parameters&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="s2">&quot;execute-script&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;value&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="s2">&quot;cd execution&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;mkdir -p /ccp_data/output&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;java -cp target/jdk-maven-example-0.0.1-SNAPSHOT.jar {{ mainclass }} 1&gt;&gt; /ccp_data/stdout.txt 2&gt;&gt; /ccp_data/stderr.txt&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;cp /tmp/file.* /ccp_data/output/&quot;</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="s2">&quot;deploy-script&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;value&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="s2">&quot;git clone {{ repository }} execution 1&gt;&gt; /ccp_data/stdout.txt 2&gt;&gt; /ccp_data/stderr.txt&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;cd execution&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;mvn clean package 1&gt; /ccp_data/stdout.txt 2&gt;&gt; /ccp_data/stderr.txt&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;cd -&quot;</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="s2">&quot;undeploy-script&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;value&quot;</span><span class="p">:[]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="s2">&quot;cancel-script&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;value&quot;</span><span class="p">:[]</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;links&quot;</span><span class="p">:[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;href&quot;</span><span class="p">:</span><span class="s2">&quot;infrastructures/nubisware-docker-swarm-nfs&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;rel&quot;</span><span class="p">:</span><span class="s2">&quot;compatibleWith&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;title&quot;</span><span class="p">:</span><span class="s2">&quot;Docker swarm with NFS on Nubis cluster&quot;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This is an example of a Method that executes Java 8 code rooted at a main class <em>example.HelloWorld</em> and cloned from a public GitHub reposiotry. The code is built with Maven.</p>
<p>The keywords section contains keywords that help in searching for the Method. The metadata fields author and context show what user has created the descriptor for the Method and in which context. Methods can also contain several category metadata items that help in classifying the Method.</p>
<p>jobControlOptions is hardocded to “async-execute” because CCP always executes Methods in an asynchronous way.</p>
<p>In the example above the Method has three inputs.</p>
<p><strong>ccpimage</strong> is required to appear exactly once. This input is always required for every Method that will be executed on CCP. It refers to the Runtime required for the Method execution. The input is a plain text string representing the reference to a container image matching the requirements of the Infrastructure. Since the example is compatible with a Docker based Infrastructure the reference is a name in Docker form <em>repository/image:versiontag</em>. This input is readonly because the default value provided at Method definition time is constrained and not editable.
<strong>repository</strong> is the URL to the Git repository to be cloned. It defaults to an example project but can be edited.
<strong>mainclass</strong> is the main class of the Java application.</p>
<p>The Method declares four example output files encoded as XML, JSON, CSV or plain text. As will be shown later, a Method is not required to return only wht it declares as outputs. The output declaration is used mainly for semantically enrich an output.</p>
<p>The additionalParameters section encodes the three scripts governing the Methods lifecycle. The lifecycle of a Method will be described in the following section. In this example, the deploy scripts takes care of cloning a Git repository passed as input parameter “reposiotry” into a target folder and build the code using Maven. The execute script builds a folder named “output”, the launches the main class of the Java application and finally copies the output files (which are created in the /tmp directory by the example Java code) to the output folder. The undeploy and cancel scripts are actually no-operations because they rely on the fact that in an environment based on containers, the clean-up operations are intrinsic.</p>
<p>It is important to note that all inputs declared for the Method can be used as variables in the scripts by putting their id in double curly brackets. There are other variables that can be useed in addition to outputs and they will be discussed in section “Execution context of a Method”.</p>
<p>The links section encodes the link to the Infrastructure that is declared to be compatible with the Method.</p>
</section>
<section id="lifecycle-of-a-method-execution">
<h3>Lifecycle of a Method execution<a class="headerlink" href="#lifecycle-of-a-method-execution" title="Permalink to this heading"></a></h3>
<p>The following Figure depicts what happens when the execution of a Method is requested by a user either by interfacing with a GUI widget of the CCP or by invoking the REST API.</p>
<figure class="align-default" id="id1">
<img alt="Lifecycle of Method execution" src="../_images/statemachine.png" />
<figcaption>
<p><span class="caption-text">Lifecycle of Method execution</span><a class="headerlink" href="#id1" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>The message carrying the execution request is sent to CCP and the execution starts. The first task puts the execution in <em>Launch</em> state. During this phase the Runtime for the execution is prepared. On a container based Infrastructure this usually resolves to using the <em>ccpimage</em> input parameter in order to fetch the container image from a reposiory and instantiatiate the container.</p>
<p>After the transition to the the Launch state, like for every other transition, the outcome of the operation is evaluated and in case of errors the process terminates by transitioning directly to the <em>Destroy</em> state thus ensuring that the infrastructure is cleaned up.</p>
<p>After a successful <em>Launch</em>, the Method execution moves into <em>Deploy</em> state. As shown by the script task decorator, this task is scripted meaning that by default its a no-operation and the commands to be performed are supplied by the creator of the Method at definition time through the <em>deploy-script</em> attribute. Example operations that could occur during this phase in a deploy script are: fetching of code on Git repositories, installation of fine grained dependencies (for example <em>pip install -r requirements.txt</em>), building of code, downloading of resource files.</p>
<p>After the <em>Deploy</em> phase, a Method execution enters the <em>Execute</em> phase. Like for the <em>Deploy</em> phase what exactly happens during this phase is determined by the <em>execute-script</em> provided by the Method creator at Method definition time. Instructions in the execute-script usually contain invocation of main code components.</p>
<p>The time spent in the <em>Execute</em> phase is limited by the Infrastructure. It is up the the Infrastructure manager to define what is the maximum amount of time allowed for Method execution. If the method allows it, the execution time can be futher limited by the user requesting the execution of a Method, by setting the <em>ccpmaxtime</em> input parameter.</p>
<p>The <em>Fetch</em> following a successful <em>Execute</em> phase is a non scriptable transition in charge of uploading the outputs of a Method execution to the Execution storage.</p>
<p>It is currently not possible to script the “Undeploy” phase because, on container based Infrastructures, the system takes autonoumously care of destroying resources at the end of a Method execution.</p>
<p>Finally, the <em>Destroy</em> phase is the time where the Infrastructure controller literally destroys the Runtime of the execution and all resources created during the previous phases.</p>
</section>
<section id="execution-context-of-a-method">
<h3>Execution context of a Method<a class="headerlink" href="#execution-context-of-a-method" title="Permalink to this heading"></a></h3>
<p>During the execution of <em>deploy-script</em>, <em>execute-script</em> and <em>undeploy-script</em> as well as during method execution it is possible to access information that is contextual to CCP, Method or Execution request.</p>
<p>Some information are accessible as template variables that can be used in the scripts with the <em>{{ var }}</em> syntax. Other useful information is passed directly to the Method execution as environmental varibales that can be accessed with the proper APIS that every programming language supports.</p>
<p>All <strong>input parameters</strong> are passed in the form of template variables to the scripts. This allows the script to adapt the input values to the requirements of the Method (using them directly passing as commandline arguments, setting as environmental variables, or writing to files).</p>
<p>There are few input parameters that are used to govern the Method execution itself rather than providing input to the Method. In particular:</p>
<ul class="simple">
<li><p><strong>ccpimage</strong> as already told is required and it is used automatically during <em>Launch</em> phase in order to instantiate a container.</p></li>
<li><p><strong>ccpnote</strong> is a special input field that when present is used to tag the executions in order to provide better visual feedback.</p></li>
<li><p><strong>ccpmaxtime</strong> can be used to limit the maximum execution time of a Method. The value is expressed in seconds and it is capped by the maximum time configured for the Infrastructure.</p></li>
<li><p><strong>ccpreplicas</strong> currently supported on Docker swarm based Infrastructures allows for creating multiple instances of a Method execution in order to obtain a coarse grained degree of parallelism.</p></li>
</ul>
<p>A set of <strong>environmental variables</strong> is passed to the Runtime inside of which the Method is executed in order to provide additional context.</p>
<p>The following two environmental valuables provide context for the execution.</p>
<ul class="simple">
<li><p><strong>ccptaskname</strong> is the id of the execution.</p></li>
<li><p><strong>ccptaskid</strong> is the index of the replica (1-based) when multiple replicas are requested with the input parameter ccpreplicas. This can be used to customise the behavior of a replica like accessing a slice of a dataset or writing output to different files.</p></li>
</ul>
<p>The following variables are related to the authentication and authorization context of the Method execution. They can be used to access D4Science services in a secure and convenient way also for very long lasting executions.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text">How to use <em>ccptaskid</em> to separate output of different replicas to different files in <em>execute-script</em>.</span><a class="headerlink" href="#id2" title="Permalink to this code"></a></div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>mkdir<span class="w"> </span>-p<span class="w"> </span>/ccp_data/output<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="nv">$RANDOM</span><span class="w"> </span>&gt;&gt;<span class="w"> </span>/ccp_data/output/<span class="sb">`</span>printenv<span class="w"> </span>ccptaskid<span class="sb">`</span>.txt
</pre></div>
</div>
</div>
<ul class="simple">
<li><p><strong>ccpiamurl</strong> is the URL of the Identity management service.</p></li>
<li><p><strong>ccpclientid</strong> is the client_id to be used for requesting token renewal.</p></li>
<li><p><strong>ccprefreshtoken</strong> is a refresh token by which new access tokens can be requested.</p></li>
<li><p><strong>ccpcontext</strong> represents the context (VO or VRE) in which the Method execution has been requested.</p></li>
</ul>
<p>As an example the following Python code shows how to use the variables to request a token renewal.</p>
<div class="literal-block-wrapper docutils container" id="id3">
<div class="code-block-caption"><span class="caption-text">How to request a login token and an UMA token for accessing D4Science service from inside Method code</span><a class="headerlink" href="#id3" title="Permalink to this code"></a></div>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span> <span class="c1">#Get auth info from env variables</span>
<span class="n">refreshtoken</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;ccprefreshtoken&quot;</span><span class="p">]</span>
<span class="n">context</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;ccpcontext&quot;</span><span class="p">]</span>
<span class="n">clientid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;ccpclientid&quot;</span><span class="p">]</span>
<span class="n">iam</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&quot;ccpiamurl&quot;</span><span class="p">]</span>
<span class="c1">#Auth related functions</span>
<span class="n">logindata</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">&#39;grant_type&#39;</span> <span class="p">:</span> <span class="s1">&#39;refresh_token&#39;</span><span class="p">,</span> <span class="s1">&#39;client_id&#39;</span> <span class="p">:</span> <span class="n">clientid</span><span class="p">,</span> <span class="s1">&#39;refresh_token&#39;</span> <span class="p">:</span> <span class="n">refreshtoken</span><span class="p">}</span>
<span class="n">loginheaders</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&quot;Accept&quot;</span> <span class="p">:</span> <span class="s2">&quot;application/json&quot;</span><span class="p">,</span> <span class="s2">&quot;Content-Type&quot;</span> <span class="p">:</span> <span class="s2">&quot;application/x-www-form-urlencoded&quot;</span><span class="p">}</span>
<span class="n">umadata</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">&#39;grant_type&#39;</span> <span class="p">:</span> <span class="s1">&#39;urn:ietf:params:oauth:grant-type:uma-ticket&#39;</span><span class="p">,</span> <span class="s1">&#39;audience&#39;</span> <span class="p">:</span> <span class="n">context</span><span class="p">}</span>
<span class="n">umaheaders</span> <span class="o">=</span> <span class="p">{</span> <span class="s2">&quot;Accept&quot;</span> <span class="p">:</span> <span class="s2">&quot;application/json&quot;</span><span class="p">,</span> <span class="s2">&quot;Content-Type&quot;</span> <span class="p">:</span> <span class="s2">&quot;application/x-www-form-urlencoded&quot;</span><span class="p">}</span>
<span class="k">def</span> <span class="nf">getToken</span><span class="p">():</span>
<span class="c1"># login with offline_token</span>
<span class="n">resp1</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">iam</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">logindata</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">loginheaders</span><span class="p">)</span>
<span class="n">jwt</span> <span class="o">=</span> <span class="n">resp1</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="c1">#get UMA token for context</span>
<span class="n">umaheaders</span><span class="p">[</span><span class="s2">&quot;Authorization&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;Bearer &quot;</span> <span class="o">+</span> <span class="n">jwt</span><span class="p">[</span><span class="s2">&quot;access_token&quot;</span><span class="p">]</span>
<span class="n">resp2</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">iam</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">umadata</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">umaheaders</span><span class="p">)</span>
<span class="k">return</span> <span class="n">resp2</span><span class="o">.</span><span class="n">json</span><span class="p">()[</span><span class="s2">&quot;access_token&quot;</span><span class="p">]</span>
<span class="c1"># Get valid token for context</span>
<span class="n">tok</span> <span class="o">=</span> <span class="n">getToken</span><span class="p">()</span>
<span class="c1"># List VRE fodler content</span>
<span class="n">vrefolder</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">workspace</span> <span class="o">+</span> <span class="s2">&quot;/vrefolder&quot;</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;Accept&quot;</span> <span class="p">:</span> <span class="s2">&quot;application/json&quot;</span><span class="p">,</span> <span class="s2">&quot;Authorization&quot;</span> <span class="p">:</span> <span class="s2">&quot;Bearer &quot;</span> <span class="o">+</span> <span class="n">tok</span><span class="p">})</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</pre></div>
</div>
</div>
<p>A similar example in bash could have the following form:</p>
<div class="literal-block-wrapper docutils container" id="id4">
<div class="code-block-caption"><span class="caption-text">How to download a file from the D4Science workspace from a private URL passed as input parameter</span><a class="headerlink" href="#id4" title="Permalink to this code"></a></div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;Getting token&quot;</span>
<span class="w"> </span><span class="nv">TOKEN</span><span class="o">=</span><span class="k">$(</span>curl<span class="w"> </span>-X<span class="w"> </span>POST<span class="w"> </span><span class="nv">$ccpiamurl</span><span class="w"> </span>-d<span class="w"> </span><span class="nv">grant_type</span><span class="o">=</span>refresh_token<span class="w"> </span>-d<span class="w"> </span><span class="nv">client_id</span><span class="o">=</span><span class="nv">$ccpclientid</span><span class="w"> </span>-d<span class="w"> </span><span class="nv">refresh_token</span><span class="o">=</span><span class="nv">$ccprefreshtoken</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;X-D4Science-Context: </span><span class="nv">$ccpcontext</span><span class="s2">&quot;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>jq<span class="w"> </span>-r<span class="w"> </span><span class="s1">&#39;.&quot;access_token&quot;&#39;</span><span class="k">)</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span>Downloading<span class="w"> </span><span class="nv">$wslink</span><span class="w"> </span>to<span class="w"> </span><span class="nv">$inputfile</span>
<span class="w"> </span>curl<span class="w"> </span>-L<span class="w"> </span><span class="nv">$wslink</span><span class="w"> </span>-o<span class="w"> </span><span class="nv">$inputfile</span><span class="w"> </span>-H<span class="w"> </span><span class="s2">&quot;Authorization: Bearer </span><span class="nv">$TOKEN</span><span class="s2">&quot;</span>
<span class="w"> </span><span class="nb">echo</span><span class="w"> </span><span class="s2">&quot;Downloaded&quot;</span>
</pre></div>
</div>
</div>
<p>A special folder is provided in the Runtime to a Method execution for storing output files. Files are currently the only way for a Method to output results by value. The folder is named <strong>/ccp_data</strong> and all the files written to this folder are returned in the context of the Execution as a zip archive.</p>
</section>
</section>
<section id="executions">
<h2>Executions<a class="headerlink" href="#executions" title="Permalink to this heading"></a></h2>
<p>An <strong>Execution</strong> represents the instatiation of a Method through a Request. The Request carries values for the inputs declared by the Method and a list of expected outputs. A dedicated data structure is created in the Execution repository as soon as an Execution request is accepted. The data structure acts as a folder that collects the request, all the outputs and all metadata generated in order to execute a Method.</p>
<p>An Execution can be exported, imported and re-executed through the CCP GUI widgets or through REST API calls.</p>
<section id="anatomy-of-an-execution">
<h3>Anatomy of an Execution<a class="headerlink" href="#anatomy-of-an-execution" title="Permalink to this heading"></a></h3>
<p>The datastructure of an Execution is meant to be as atomic and as explicative as possible.
The following is a representation of the data structure representing an Execution.</p>
<ul class="simple">
<li><p><strong>metadata</strong></p>
<ul>
<li><p><strong>request.json</strong> # The JSON message that requested the Execution</p></li>
<li><p><strong>method.json</strong> # The JSON Method descriptor</p></li>
<li><p><strong>infrastructure.json</strong> # The JSON Infrastructure descriptor</p></li>
<li><p><strong>instance.json</strong> # The JSON descriptor of the container that played as the Runtime of the Execution</p></li>
</ul>
</li>
<li><p><strong>auth</strong></p>
<ul>
<li><p><strong>jwt.json</strong> # Authorization information of the user requesting the Execution</p></li>
</ul>
</li>
<li><p><strong>outputs</strong></p>
<ul>
<li><p><strong>output.zip</strong> # Zip archive of all output files and folders.</p></li>
</ul>
</li>
</ul>
</section>
<section id="method-and-execution-storage">
<h3>Method and Execution storage<a class="headerlink" href="#method-and-execution-storage" title="Permalink to this heading"></a></h3>
<p>In ordder to be able to execute a Method or to operate on an Execution they need to be kept inside the <strong>Workbench</strong>. The Workbench can be seen as a sort of short lived storage area that resides closely to the CCP core components.</p>
<p>A Method that is on the Workbench can be cloned, edited, executed, deleted, exported or archived to a offline storage area. The offline storage area is a dedicated folder CCP/methods on a users D4Science workspace. When exported to file or archive to the worksapce a MEthod is a JSON file named like the Methods title and version.</p>
<p>An Execution that is on the workbench can be browsed, downloaded, re-executed, deleted or archived to an offline storage area which resides in a dedicated folder CCP/executions on a users workspace. When downloaded to a file or archived to the workspace, an Execution is a zip archive containing a compressed binary with the structure described in the previous section.</p>
<p>Methods and Executions can be reimported to the Workbench Beither by uploading exported files or passing the “sharable links” obtained from the workspace.</p>
</section>
</section>
<section id="ui-widgets">
<h2>UI Widgets<a class="headerlink" href="#ui-widgets" title="Permalink to this heading"></a></h2>
<p>A set of graphical user interaction (GUI) widgets are provided in order to allow a user to interact from browser based applications with Methods and Executions stored in the Workbench.</p>
<section id="method-list">
<h3>Method list<a class="headerlink" href="#method-list" title="Permalink to this heading"></a></h3>
<p>The <em>Method list</em> widget is a visual representantion of the list of Methods that a user is able to access in a given context either because he/she is the owner or because they are shared in the context.</p>
<p>The following Figure shows an example visualization of the Method list.</p>
<figure class="align-default" id="id5">
<img alt="Method list widget" src="../_images/methodlistwidget.png" />
<figcaption>
<p><span class="caption-text">Method list widget</span><a class="headerlink" href="#id5" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>The Method list widget is comprised of a toolbar, a search field and the list of Methods. The Methods are organized by categories as shown in [1]. For every Method the title, version, author and description are reported in the first two lines [2]. As additional information tags and compatible Infrastructure are shown [3]. There is the possibility to download a Method or a whole class and to see how many of the shown Methods are executable [4]. Methods can be not executable if their compatible Infrastrucure is not known or available. A per MEthod tollbar [5] allows to download, edit or execute a Method for. From the global toolbar it is possible to refresh the list or upload a Method from a file [6] and also to reimport an archived Method from the workspace by copying and pasting the shareable link into the proper field and clicking on the button [7].</p>
</section>
<section id="method-editor">
<h3>Method editor<a class="headerlink" href="#method-editor" title="Permalink to this heading"></a></h3>
<p>The <em>Method editor</em> widget is a visual tool for creating, deleting, editing, cloning or deriving a Method descriptor.</p>
<p>The following Figure shows an example visualization of the Method editor.</p>
<figure class="align-default" id="id6">
<img alt="Method editor widget" src="../_images/methodeditorwidget.png" />
<figcaption>
<p><span class="caption-text">Method editor widget</span><a class="headerlink" href="#id6" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>From the global toolbar [1] it is possible to save the edited Method or delete it or clear all the form fields. The metadata area [2] contains the controls to define all the metadata of a Method including title, version, description, tags, categories. It is also possible to choose a compatible Infrastructure from the available ones. In the input definition area [3] the user can define all the input parameters with their type, format, encoding, cardinality and default values. In the output definition area [4] the user can define all the output files that can be expected from an Execution with their type, format, encoding and cardinality. Shortcuts are added to define with one click the standard output and error chnannels of a Method. In the scripting area [5] the deploy, execute and undeploy script can be defined.</p>
<p>Once the Method is saved the user will automatically be added as the Author. If the user defines the method to be public, the Method is made available to all members of the context (VO or VRE) in which the operation occurred.</p>
</section>
<section id="method-execution-form">
<h3>Method execution form<a class="headerlink" href="#method-execution-form" title="Permalink to this heading"></a></h3>
<p>The <em>Method execution form</em> widget is a visual tool for requesting the execution of a Method.</p>
<p>The following Figure shows an example visualization of the Method execution form.</p>
<figure class="align-default" id="id7">
<img alt="Method execution form" src="../_images/executionformwidget.png" />
<figcaption>
<p><span class="caption-text">Method execution form</span><a class="headerlink" href="#id7" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>In the area labelled with [1], the principal metadata of the Method is shown. In the Inputs area [2] it is possible to edit the input values that are passed to the Execution. The input fields try to match as close as possible the constraints defined for the input in the Method descriptor. The execute button [4] triggers the sending of the execution request. A code generator widget [5] can be used in order to download code snippets that act as working examples for requesting the Execution programmatically through the CCP APIs (see <a class="reference internal" href="#rest"><span class="std std-ref">REST APIs: Interacting with Methods and Executions programmatically</span></a>). Currently Python 3, R, Jupyter Notebook and Julia are supported but the list will grow in the future.</p>
<p>A direct link is provided that, when navigated to, will open the execution form with exactly the same parametrization that has been submitted for execution.</p>
</section>
<section id="execution-monitor">
<h3>Execution monitor<a class="headerlink" href="#execution-monitor" title="Permalink to this heading"></a></h3>
<p>The <em>Execution Monitor</em> widget is a visual tool for monitoring Executions.</p>
<p>The following Figure shows an example visualization of the Execution monitor.</p>
<figure class="align-default" id="id8">
<img alt="Execution monitor" src="../_images/executionmonitorwidget.png" />
<figcaption>
<p><span class="caption-text">Execution monitor</span><a class="headerlink" href="#id8" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>The list of Executions are organized by their Method names [1]. For every Method the number of executions in the different states (accepted, running, successful, failed) is reported. When expanding a Method the list of all Executions is shown [2]. Every list item reports information about the Method version, the status, timing, Infrastructure and Runtime of the Execution. When outputs are available a link to download them is shown [3]. Actions that can be performed on an Execution [5] are download as zip archive, archive to workspace, download provenance descriptor in Prov-O format, re-execute and delete. An Execution item can also be drag and dropped onto the Execution form widget in order to prepare a request for a new onne. Code for programmatically requesting the same Execution can be generated with a proper code generation widget [6]. Currently Python 3, R, Julia and Jupyter Notebooks are currently supported.</p>
<p>A direct link is shown that allows, when navigated to, to open the execution form with exatly the same parametrization of the execution itself.</p>
<p>By using the triggers on the global toolbar [6] the list of Executions can be refreshed, a previously exported Execution can be reimported from a local zip file and archived Exections can be re-imported from their sharable workspace link.</p>
</section>
</section>
<section id="rest-apis-interacting-with-methods-and-executions-programmatically">
<span id="rest"></span><h2>REST APIs: Interacting with Methods and Executions programmatically<a class="headerlink" href="#rest-apis-interacting-with-methods-and-executions-programmatically" title="Permalink to this heading"></a></h2>
<p>Most of the services that build up CCP are accessible programmatically via REST endpoints.
In particular, listing Methods (Jobs), executing them or getting infromation on running executions (jobStatus) are accessible through a standard API defined by OGC (Open Geospatial Consortium).
The REST API is Processes 1.2 described at (<a class="reference external" href="https://ogcapi.ogc.org/processes/">https://ogcapi.ogc.org/processes/</a>) and can be considered a modern rework of the former WPS spcification.</p>
<p>The CCP REST API is documented as OpenAPI 3 specification at (<a class="reference external" href="https://app.swaggerhub.com/apis/OGC/ogcapi-processes-1-example-1/1.0.0">https://app.swaggerhub.com/apis/OGC/ogcapi-processes-1-example-1/1.0.0</a>).</p>
<p>Through the code generation widgets available in the UI elements described above, it is possible to obtain stubs that show how to interact programmatically with CCP in order to request a Method execution or re-execution and to monitor the evolution.</p>
<p>The following is an example code stub generated for the R programming language.</p>
<div class="literal-block-wrapper docutils container" id="id9">
<div class="code-block-caption"><span class="caption-text">Example code for requesting a Method execution on CCP</span><a class="headerlink" href="#id9" title="Permalink to this code"></a></div>
<div class="highlight-R notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Dependencies</span>
<span class="w"> </span><span class="nf">library</span><span class="p">(</span><span class="n">httr</span><span class="p">)</span>
<span class="w"> </span><span class="nf">library</span><span class="p">(</span><span class="n">jsonlite</span><span class="p">)</span>
<span class="w"> </span><span class="nf">library</span><span class="p">(</span><span class="n">rstudioapi</span><span class="p">)</span>
<span class="w"> </span><span class="c1"># Init</span>
<span class="w"> </span><span class="n">user</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;usrname&#39;</span>
<span class="w"> </span><span class="n">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;a vre&#39;</span>
<span class="w"> </span><span class="n">auth_ep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;https://authep&#39;</span>
<span class="w"> </span><span class="n">client_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;aclietnid&#39;</span>
<span class="w"> </span><span class="n">ccp_ep</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;https://ccpep&#39;</span>
<span class="w"> </span><span class="n">getToken</span><span class="w"> </span><span class="o">&lt;-</span><span class="w"> </span><span class="nf">function</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">#login</span>
<span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">POST</span><span class="p">(</span><span class="n">auth_ep</span><span class="p">,</span><span class="w"> </span><span class="n">body</span><span class="o">=</span><span class="nf">list</span><span class="p">(</span><span class="s">&#39;grant_type&#39;</span><span class="o">=</span><span class="s">&#39;password&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;client_id&#39;</span><span class="o">=</span><span class="n">client_id</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;username&#39;</span><span class="o">=</span><span class="n">user</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;password&#39;</span><span class="o">=</span><span class="n">pwd</span><span class="p">),</span><span class="w"> </span><span class="n">encode</span><span class="o">=</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;form&#39;</span><span class="p">),</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Content-Type&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;application/x-www-form-urlencoded&#39;</span><span class="p">)))</span>
<span class="w"> </span><span class="n">tok</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">fromJSON</span><span class="p">(</span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">))</span>
<span class="w"> </span><span class="c1">#authorize</span>
<span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">POST</span><span class="p">(</span><span class="n">auth_ep</span><span class="p">,</span><span class="w"> </span><span class="n">body</span><span class="o">=</span><span class="nf">list</span><span class="p">(</span><span class="s">&#39;grant_type&#39;</span><span class="o">=</span><span class="s">&#39;urn:ietf:params:oauth:grant-type:uma-ticket&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;audience&#39;</span><span class="o">=</span><span class="n">context</span><span class="p">),</span><span class="w"> </span><span class="n">encode</span><span class="o">=</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;form&#39;</span><span class="p">),</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Content-Type&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;application/x-www-form-urlencoded&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;Authorization&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Bearer&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">tok</span><span class="p">[</span><span class="s">&#39;access_token&#39;</span><span class="p">],</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">))))</span>
<span class="w"> </span><span class="n">jwt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">fromJSON</span><span class="p">(</span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">))[</span><span class="s">&#39;access_token&#39;</span><span class="p">]</span>
<span class="w"> </span><span class="nf">return </span><span class="p">(</span><span class="n">jwt</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1"># request in JSON</span>
<span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">fromJSON</span><span class="p">(</span><span class="s">&#39;{</span>
<span class="s"> &quot;inputs&quot;:{</span>
<span class="s"> &quot;ccpimage&quot;:&quot;bash&quot;,</span>
<span class="s"> &quot;ccpreplicas&quot;:&quot;1&quot;</span>
<span class="s"> },</span>
<span class="s"> &quot;outputs&quot;:{</span>
<span class="s"> &quot;output&quot;:{</span>
<span class="s"> &quot;transmissionMode&quot;:&quot;value&quot;</span>
<span class="s"> }</span>
<span class="s"> },</span>
<span class="s"> &quot;response&quot;:&quot;raw&quot;</span>
<span class="s"> }&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="c1"># Auth code</span>
<span class="w"> </span><span class="n">pwd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">askForPassword</span><span class="p">(</span><span class="s">&#39;Password to login&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="n">jwt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">getToken</span><span class="p">()</span>
<span class="w"> </span><span class="c1"># Request Method execution</span>
<span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="n">ccp_ep</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;processes/{methodid}/execution&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">POST</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="n">body</span><span class="o">=</span><span class="n">request</span><span class="p">,</span><span class="w"> </span><span class="n">encode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;json&#39;</span><span class="p">,</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Authorization&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Bearer&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jwt</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">))))</span>
<span class="w"> </span><span class="nf">if</span><span class="p">(</span><span class="nf">status_code</span><span class="p">(</span><span class="n">res</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">201</span><span class="p">){</span>
<span class="w"> </span><span class="n">jobStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">fromJSON</span><span class="p">(</span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span><span class="n">else</span><span class="p">{</span>
<span class="w"> </span><span class="nf">stop</span><span class="p">(</span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Unable to start execution:&#39;</span><span class="p">,</span><span class="w"> </span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">)))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1"># Poll for jobstatus</span>
<span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="n">ccp_ep</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;jobs&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;jobID&#39;</span><span class="p">],</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="nf">while </span><span class="p">(</span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;status&#39;</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&#39;successful&#39;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;status&#39;</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="s">&#39;failed&#39;</span><span class="p">){</span>
<span class="w"> </span><span class="nf">print</span><span class="p">(</span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;[&#39;</span><span class="p">,</span><span class="nf">Sys.time</span><span class="p">(),</span><span class="s">&#39;]&#39;</span><span class="p">,</span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;status&#39;</span><span class="p">],</span><span class="s">&#39;: &#39;</span><span class="p">,</span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;message&#39;</span><span class="p">]))</span>
<span class="w"> </span><span class="nf">Sys.sleep</span><span class="p">(</span><span class="m">5</span><span class="p">)</span>
<span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">GET</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Authorization&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Bearer&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jwt</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">))))</span>
<span class="w"> </span><span class="nf">if</span><span class="p">(</span><span class="nf">status_code</span><span class="p">(</span><span class="n">res</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">200</span><span class="p">){</span>
<span class="w"> </span><span class="n">jobStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">fromJSON</span><span class="p">(</span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span><span class="n">else</span><span class="w"> </span><span class="nf">if</span><span class="p">(</span><span class="nf">status_code</span><span class="p">(</span><span class="n">res</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="m">401</span><span class="p">){</span>
<span class="w"> </span><span class="n">jwt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">getToken</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span><span class="n">else</span><span class="p">{</span>
<span class="w"> </span><span class="nf">stop</span><span class="p">(</span><span class="s">&#39;Unable to poll for execution status&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nf">print</span><span class="p">(</span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;[&#39;</span><span class="p">,</span><span class="nf">Sys.time</span><span class="p">(),</span><span class="s">&#39;]&#39;</span><span class="p">,</span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;status&#39;</span><span class="p">],</span><span class="s">&#39;: &#39;</span><span class="p">,</span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;message&#39;</span><span class="p">]))</span>
<span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="n">ccp_ep</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;executions&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;jobID&#39;</span><span class="p">],</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">GET</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Accept&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;application/json&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;Authorization&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Bearer&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jwt</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">))))</span>
<span class="w"> </span><span class="nf">print</span><span class="p">(</span><span class="nf">fromJSON</span><span class="p">(</span><span class="nf">content</span><span class="p">(</span><span class="n">res</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;text&#39;</span><span class="p">)))</span>
<span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="n">ccp_ep</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;executions&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jobStatus</span><span class="p">[</span><span class="s">&#39;jobID&#39;</span><span class="p">],</span><span class="w"> </span><span class="s">&#39;outputs/output.zip&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="w"> </span><span class="nf">GET</span><span class="p">(</span><span class="n">url</span><span class="p">,</span><span class="w"> </span><span class="nf">add_headers</span><span class="p">(</span><span class="nf">c</span><span class="p">(</span><span class="s">&#39;Accept&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">&#39;application/json&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;Authorization&#39;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nf">paste</span><span class="p">(</span><span class="s">&#39;Bearer&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">jwt</span><span class="p">,</span><span class="w"> </span><span class="n">sep</span><span class="o">=</span><span class="s">&#39; &#39;</span><span class="p">))),</span>
<span class="w"> </span><span class="nf">write_disk</span><span class="p">(</span><span class="s">&#39;./output.zip&#39;</span><span class="p">,</span><span class="w"> </span><span class="n">overwrite</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">FALSE</span><span class="p">))</span>
</pre></div>
</div>
</div>
</section>
</section>
</div>
</div>
<footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
<a href="../introduction.html" class="btn btn-neutral float-left" title="Introduction" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>&#169; Copyright 2023, Marco Lettere.</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script>
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>