<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <title>pylorax.api.v1 &mdash; Lorax 33.10 documentation</title>
  

  
  
  
  

  
  <script type="text/javascript" src="../../../_static/js/modernizr.min.js"></script>
  
    
      <script type="text/javascript" id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
        <script src="../../../_static/jquery.js"></script>
        <script src="../../../_static/underscore.js"></script>
        <script src="../../../_static/doctools.js"></script>
        <script src="../../../_static/language_data.js"></script>
    
    <script type="text/javascript" src="../../../_static/js/theme.js"></script>

    

  
  <link rel="stylesheet" href="../../../_static/css/theme.css" type="text/css" />
  <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
    <link rel="index" title="Index" href="../../../genindex.html" />
    <link rel="search" title="Search" href="../../../search.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"> Lorax
          

          
          </a>

          
            
            
              <div class="version">
                33.10
              </div>
            
          

          
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../../../search.html" method="get">
    <input type="text" name="q" placeholder="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="main navigation">
          
            
            
              
            
            
              <ul>
<li class="toctree-l1"><a class="reference internal" href="../../../intro.html">Introduction to Lorax</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../intro.html#before-lorax">Before Lorax</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../lorax.html">Lorax</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../livemedia-creator.html">livemedia-creator</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../lorax-composer.html">lorax-composer</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../composer-cli.html">composer-cli</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../mkksiso.html">mkksiso</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../product-images.html">Product and Updates Images</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../../modules.html">src</a></li>
</ul>

            
          
        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" aria-label="top navigation">
        
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../../../index.html">Lorax</a>
        
      </nav>


      <div class="wy-nav-content">
        
        <div class="rst-content">
        
          















<div role="navigation" aria-label="breadcrumbs navigation">

  <ul class="wy-breadcrumbs">
    
      <li><a href="../../../index.html">Docs</a> &raquo;</li>
        
          <li><a href="../../index.html">Module code</a> &raquo;</li>
        
          <li><a href="../../pylorax.html">pylorax</a> &raquo;</li>
        
      <li>pylorax.api.v1</li>
    
    
      <li class="wy-breadcrumbs-aside">
        
      </li>
    
  </ul>

  
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
            
  <h1>Source code for pylorax.api.v1</h1><div class="highlight"><pre>
<span></span><span class="c1">#</span>
<span class="c1"># Copyright (C) 2019  Red Hat, Inc.</span>
<span class="c1">#</span>
<span class="c1"># This program is free software; you can redistribute it and/or modify</span>
<span class="c1"># it under the terms of the GNU General Public License as published by</span>
<span class="c1"># the Free Software Foundation; either version 2 of the License, or</span>
<span class="c1"># (at your option) any later version.</span>
<span class="c1">#</span>
<span class="c1"># This program is distributed in the hope that it will be useful,</span>
<span class="c1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
<span class="c1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span>
<span class="c1"># GNU General Public License for more details.</span>
<span class="c1">#</span>
<span class="c1"># You should have received a copy of the GNU General Public License</span>
<span class="c1"># along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span>
<span class="c1">#</span>
<span class="sd">&quot;&quot;&quot; Setup v1 of the API server</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s2">&quot;lorax-composer&quot;</span><span class="p">)</span>

<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">jsonify</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">current_app</span> <span class="k">as</span> <span class="n">api</span>

<span class="kn">from</span> <span class="nn">lifted.queue</span> <span class="kn">import</span> <span class="n">get_upload</span><span class="p">,</span> <span class="n">reset_upload</span><span class="p">,</span> <span class="n">cancel_upload</span><span class="p">,</span> <span class="n">delete_upload</span>
<span class="kn">from</span> <span class="nn">lifted.providers</span> <span class="kn">import</span> <span class="n">list_providers</span><span class="p">,</span> <span class="n">resolve_provider</span><span class="p">,</span> <span class="n">load_profiles</span><span class="p">,</span> <span class="n">validate_settings</span><span class="p">,</span> <span class="n">save_settings</span>
<span class="kn">from</span> <span class="nn">lifted.providers</span> <span class="kn">import</span> <span class="n">load_settings</span><span class="p">,</span> <span class="n">delete_profile</span>
<span class="kn">from</span> <span class="nn">pylorax.api.checkparams</span> <span class="kn">import</span> <span class="n">checkparams</span>
<span class="kn">from</span> <span class="nn">pylorax.api.compose</span> <span class="kn">import</span> <span class="n">start_build</span>
<span class="kn">from</span> <span class="nn">pylorax.api.errors</span> <span class="kn">import</span> <span class="n">BAD_COMPOSE_TYPE</span><span class="p">,</span> <span class="n">BUILD_FAILED</span><span class="p">,</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="n">MISSING_POST</span><span class="p">,</span> <span class="n">PROJECTS_ERROR</span>
<span class="kn">from</span> <span class="nn">pylorax.api.errors</span> <span class="kn">import</span> <span class="n">SYSTEM_SOURCE</span><span class="p">,</span> <span class="n">UNKNOWN_BLUEPRINT</span><span class="p">,</span> <span class="n">UNKNOWN_SOURCE</span><span class="p">,</span> <span class="n">UNKNOWN_UUID</span><span class="p">,</span> <span class="n">UPLOAD_ERROR</span>
<span class="kn">from</span> <span class="nn">pylorax.api.errors</span> <span class="kn">import</span> <span class="n">COMPOSE_ERROR</span>
<span class="kn">from</span> <span class="nn">pylorax.api.flask_blueprint</span> <span class="kn">import</span> <span class="n">BlueprintSkip</span>
<span class="kn">from</span> <span class="nn">pylorax.api.queue</span> <span class="kn">import</span> <span class="n">queue_status</span><span class="p">,</span> <span class="n">build_status</span><span class="p">,</span> <span class="n">uuid_status</span><span class="p">,</span> <span class="n">uuid_schedule_upload</span><span class="p">,</span> <span class="n">uuid_remove_upload</span>
<span class="kn">from</span> <span class="nn">pylorax.api.queue</span> <span class="kn">import</span> <span class="n">uuid_info</span>
<span class="kn">from</span> <span class="nn">pylorax.api.projects</span> <span class="kn">import</span> <span class="n">get_repo_sources</span><span class="p">,</span> <span class="n">repo_to_source</span>
<span class="kn">from</span> <span class="nn">pylorax.api.projects</span> <span class="kn">import</span> <span class="n">new_repo_source</span>
<span class="kn">from</span> <span class="nn">pylorax.api.regexes</span> <span class="kn">import</span> <span class="n">VALID_API_STRING</span><span class="p">,</span> <span class="n">VALID_BLUEPRINT_NAME</span>
<span class="kn">import</span> <span class="nn">pylorax.api.toml</span> <span class="k">as</span> <span class="nn">toml</span>
<span class="kn">from</span> <span class="nn">pylorax.api.utils</span> <span class="kn">import</span> <span class="n">blueprint_exists</span>


<span class="c1"># Create the v1 routes Blueprint with skip_routes support</span>
<span class="n">v1_api</span> <span class="o">=</span> <span class="n">BlueprintSkip</span><span class="p">(</span><span class="s2">&quot;v1_routes&quot;</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">)</span>

<div class="viewcode-block" id="v1_projects_source_info"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_projects_source_info">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/projects/source/info&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;source_ids&#39;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">})</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/projects/source/info/&lt;source_ids&gt;&quot;</span><span class="p">)</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;source_ids&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no source names given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_projects_source_info</span><span class="p">(</span><span class="n">source_ids</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Return detailed info about the list of sources</span>

<span class="sd">    **/api/v1/projects/source/info/&lt;source-ids&gt;**</span>

<span class="sd">      Return information about the comma-separated list of source ids. Or all of the</span>
<span class="sd">      sources if &#39;*&#39; is passed. Note that general globbing is not supported, only &#39;*&#39;.</span>

<span class="sd">      Immutable system sources will have the &quot;system&quot; field set to true. User added sources</span>
<span class="sd">      will have it set to false. System sources cannot be changed or deleted.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;errors&quot;: [],</span>
<span class="sd">            &quot;sources&quot;: {</span>
<span class="sd">              &quot;fedora&quot;: {</span>
<span class="sd">                &quot;check_gpg&quot;: true,</span>
<span class="sd">                &quot;check_ssl&quot;: true,</span>
<span class="sd">                &quot;gpgkey_urls&quot;: [</span>
<span class="sd">                  &quot;file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-28-x86_64&quot;</span>
<span class="sd">                ],</span>
<span class="sd">                &quot;id&quot;: &quot;fedora&quot;,</span>
<span class="sd">                &quot;name&quot;: &quot;Fedora $releasever - $basearch&quot;,</span>
<span class="sd">                &quot;proxy&quot;: &quot;http://proxy.brianlane.com:8123&quot;,</span>
<span class="sd">                &quot;system&quot;: true,</span>
<span class="sd">                &quot;type&quot;: &quot;yum-metalink&quot;,</span>
<span class="sd">                &quot;url&quot;: &quot;https://mirrors.fedoraproject.org/metalink?repo=fedora-28&amp;arch=x86_64&quot;</span>
<span class="sd">              }</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">    In v0 the ``name`` field was used for the id (a short name for the repo). In v1 ``name`` changed</span>
<span class="sd">    to ``id`` and ``name`` is now used for the longer descriptive name of the repository.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">source_ids</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="n">out_fmt</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;format&quot;</span><span class="p">,</span> <span class="s2">&quot;json&quot;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">out_fmt</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in format argument&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="c1"># Return info on all of the sources</span>
    <span class="k">if</span> <span class="n">source_ids</span> <span class="o">==</span> <span class="s2">&quot;*&quot;</span><span class="p">:</span>
        <span class="k">with</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
            <span class="n">source_ids</span> <span class="o">=</span> <span class="s2">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">id</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">dbo</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">iter_enabled</span><span class="p">())</span>

    <span class="n">sources</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">system_sources</span> <span class="o">=</span> <span class="n">get_repo_sources</span><span class="p">(</span><span class="s2">&quot;/etc/yum.repos.d/*.repo&quot;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">source</span> <span class="ow">in</span> <span class="n">source_ids</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">):</span>
        <span class="k">with</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
            <span class="n">repo</span> <span class="o">=</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">dbo</span><span class="o">.</span><span class="n">repos</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">repo</span><span class="p">:</span>
            <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_SOURCE</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> is not a valid source&quot;</span> <span class="o">%</span> <span class="n">source</span><span class="p">})</span>
            <span class="k">continue</span>
        <span class="n">sources</span><span class="p">[</span><span class="n">repo</span><span class="o">.</span><span class="n">id</span><span class="p">]</span> <span class="o">=</span> <span class="n">repo_to_source</span><span class="p">(</span><span class="n">repo</span><span class="p">,</span> <span class="n">repo</span><span class="o">.</span><span class="n">id</span> <span class="ow">in</span> <span class="n">system_sources</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">out_fmt</span> <span class="o">==</span> <span class="s2">&quot;toml&quot;</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">errors</span><span class="p">:</span>
        <span class="c1"># With TOML output we just want to dump the raw sources, skipping the errors</span>
        <span class="k">return</span> <span class="n">toml</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">sources</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">out_fmt</span> <span class="o">==</span> <span class="s2">&quot;toml&quot;</span> <span class="ow">and</span> <span class="n">errors</span><span class="p">:</span>
        <span class="c1"># TOML requested, but there was an error</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">),</span> <span class="mi">400</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">sources</span><span class="o">=</span><span class="n">sources</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_projects_source_new"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_projects_source_new">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/projects/source/new&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">v1_projects_source_new</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Add a new package source. Or change an existing one</span>

<span class="sd">    **POST /api/v1/projects/source/new**</span>

<span class="sd">      Add (or change) a source for use when depsolving blueprints and composing images.</span>

<span class="sd">      The ``proxy`` and ``gpgkey_urls`` entries are optional. All of the others are required. The supported</span>
<span class="sd">      types for the urls are:</span>

<span class="sd">      * ``yum-baseurl`` is a URL to a yum repository.</span>
<span class="sd">      * ``yum-mirrorlist`` is a URL for a mirrorlist.</span>
<span class="sd">      * ``yum-metalink`` is a URL for a metalink.</span>

<span class="sd">      If ``check_ssl`` is true the https certificates must be valid. If they are self-signed you can either set</span>
<span class="sd">      this to false, or add your Certificate Authority to the host system.</span>

<span class="sd">      If ``check_gpg`` is true the GPG key must either be installed on the host system, or ``gpgkey_urls``</span>
<span class="sd">      should point to it.</span>

<span class="sd">      You can edit an existing source (other than system sources), by doing a POST</span>
<span class="sd">      of the new version of the source. It will overwrite the previous one.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">              &quot;id&quot;: &quot;custom-source-1&quot;,</span>
<span class="sd">              &quot;name&quot;: &quot;Custom Package Source #1&quot;,</span>
<span class="sd">              &quot;url&quot;: &quot;https://url/path/to/repository/&quot;,</span>
<span class="sd">              &quot;type&quot;: &quot;yum-baseurl&quot;,</span>
<span class="sd">              &quot;check_ssl&quot;: true,</span>
<span class="sd">              &quot;check_gpg&quot;: true,</span>
<span class="sd">              &quot;gpgkey_urls&quot;: [</span>
<span class="sd">                  &quot;https://url/path/to/gpg-key&quot;</span>
<span class="sd">              ]</span>
<span class="sd">          }</span>

<span class="sd">    In v0 the ``name`` field was used for the id (a short name for the repo). In v1 ``name`` changed</span>
<span class="sd">    to ``id`` and ``name`` is now used for the longer descriptive name of the repository.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;Content-Type&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s2">&quot;text/x-toml&quot;</span><span class="p">:</span>
        <span class="n">source</span> <span class="o">=</span> <span class="n">toml</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">source</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_json</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

    <span class="c1"># Check for id in source, return error if not</span>
    <span class="k">if</span> <span class="s2">&quot;id&quot;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">source</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_SOURCE</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;&#39;id&#39; field is missing from API v1 request.&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="n">system_sources</span> <span class="o">=</span> <span class="n">get_repo_sources</span><span class="p">(</span><span class="s2">&quot;/etc/yum.repos.d/*.repo&quot;</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">source</span><span class="p">[</span><span class="s2">&quot;id&quot;</span><span class="p">]</span> <span class="ow">in</span> <span class="n">system_sources</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">SYSTEM_SOURCE</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> is a system source, it cannot be changed.&quot;</span> <span class="o">%</span> <span class="n">source</span><span class="p">[</span><span class="s2">&quot;id&quot;</span><span class="p">]}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="c1"># Remove it from the RepoDict (NOTE that this isn&#39;t explicitly supported by the DNF API)</span>
        <span class="k">with</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
            <span class="n">repo_dir</span> <span class="o">=</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;composer&quot;</span><span class="p">,</span> <span class="s2">&quot;repo_dir&quot;</span><span class="p">)</span>
            <span class="n">new_repo_source</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">dbo</span><span class="p">,</span> <span class="n">source</span><span class="p">[</span><span class="s2">&quot;id&quot;</span><span class="p">],</span> <span class="n">source</span><span class="p">,</span> <span class="n">repo_dir</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">PROJECTS_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>

    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_compose_start"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_start">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">v1_compose_start</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Start a compose</span>

<span class="sd">    The body of the post should have these fields:</span>
<span class="sd">      blueprint_name - The blueprint name from /blueprints/list/</span>
<span class="sd">      compose_type   - The type of output to create, from /compose/types</span>
<span class="sd">      branch         - Optional, defaults to master, selects the git branch to use for the blueprint.</span>

<span class="sd">    **POST /api/v1/compose**</span>

<span class="sd">      Start a compose. The content type should be &#39;application/json&#39; and the body of the POST</span>
<span class="sd">      should look like this. The &quot;upload&quot; object is optional.</span>

<span class="sd">      The upload object can specify either a pre-existing profile to use (as returned by</span>
<span class="sd">      `/uploads/providers`) or one-time use settings for the provider.</span>

<span class="sd">      Example with upload profile::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;blueprint_name&quot;: &quot;http-server&quot;,</span>
<span class="sd">            &quot;compose_type&quot;: &quot;tar&quot;,</span>
<span class="sd">            &quot;branch&quot;: &quot;master&quot;,</span>
<span class="sd">            &quot;upload&quot;: {</span>
<span class="sd">              &quot;image_name&quot;: &quot;My Image&quot;,</span>
<span class="sd">              &quot;provider&quot;: &quot;azure&quot;,</span>
<span class="sd">              &quot;profile&quot;: &quot;production-azure-settings&quot;</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">      Example with upload settings::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;blueprint_name&quot;: &quot;http-server&quot;,</span>
<span class="sd">            &quot;compose_type&quot;: &quot;tar&quot;,</span>
<span class="sd">            &quot;branch&quot;: &quot;master&quot;,</span>
<span class="sd">            &quot;upload&quot;: {</span>
<span class="sd">              &quot;image_name&quot;: &quot;My Image&quot;,</span>
<span class="sd">              &quot;provider&quot;: &quot;azure&quot;,</span>
<span class="sd">              &quot;settings&quot;: {</span>
<span class="sd">                &quot;resource_group&quot;: &quot;SOMEBODY&quot;,</span>
<span class="sd">                &quot;storage_account_name&quot;: &quot;ONCE&quot;,</span>
<span class="sd">                &quot;storage_container&quot;: &quot;TOLD&quot;,</span>
<span class="sd">                &quot;location&quot;: &quot;ME&quot;,</span>
<span class="sd">                &quot;subscription_id&quot;: &quot;THE&quot;,</span>
<span class="sd">                &quot;client_id&quot;: &quot;WORLD&quot;,</span>
<span class="sd">                &quot;secret&quot;: &quot;IS&quot;,</span>
<span class="sd">                &quot;tenant&quot;: &quot;GONNA&quot;</span>
<span class="sd">              }</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">      Pass it the name of the blueprint, the type of output (from</span>
<span class="sd">      &#39;/api/v1/compose/types&#39;), and the blueprint branch to use. &#39;branch&#39; is</span>
<span class="sd">      optional and will default to master. It will create a new build and add</span>
<span class="sd">      it to the queue. It returns the build uuid and a status if it succeeds.</span>
<span class="sd">      If an &quot;upload&quot; is given, it will schedule an upload to run when the build</span>
<span class="sd">      finishes.</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;build_id&quot;: &quot;e6fa6db4-9c81-4b70-870f-a697ca405cdf&quot;,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;572eb0d0-5348-4600-9666-14526ba628bb&quot;,</span>
<span class="sd">            &quot;status&quot;: true</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="c1"># Passing ?test=1 will generate a fake FAILED compose.</span>
    <span class="c1"># Passing ?test=2 will generate a fake FINISHED compose.</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">test_mode</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;test&quot;</span><span class="p">,</span> <span class="s2">&quot;0&quot;</span><span class="p">))</span>
    <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
        <span class="n">test_mode</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="n">compose</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_json</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

    <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">compose</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">MISSING_POST</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Missing POST body&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="k">if</span> <span class="s2">&quot;blueprint_name&quot;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">compose</span><span class="p">:</span>
        <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_BLUEPRINT</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;No &#39;blueprint_name&#39; in the JSON request&quot;</span><span class="p">})</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">blueprint_name</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;blueprint_name&quot;</span><span class="p">]</span>

    <span class="k">if</span> <span class="s2">&quot;branch&quot;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">compose</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;branch&quot;</span><span class="p">]:</span>
        <span class="n">branch</span> <span class="o">=</span> <span class="s2">&quot;master&quot;</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">branch</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;branch&quot;</span><span class="p">]</span>

    <span class="k">if</span> <span class="s2">&quot;compose_type&quot;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">compose</span><span class="p">:</span>
        <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">BAD_COMPOSE_TYPE</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;No &#39;compose_type&#39; in the JSON request&quot;</span><span class="p">})</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">compose_type</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;compose_type&quot;</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">VALID_BLUEPRINT_NAME</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">blueprint_name</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">})</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">blueprint_exists</span><span class="p">(</span><span class="n">api</span><span class="p">,</span> <span class="n">branch</span><span class="p">,</span> <span class="n">blueprint_name</span><span class="p">):</span>
        <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_BLUEPRINT</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Unknown blueprint name: </span><span class="si">%s</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="n">blueprint_name</span><span class="p">})</span>

    <span class="k">if</span> <span class="s2">&quot;upload&quot;</span> <span class="ow">in</span> <span class="n">compose</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">image_name</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">][</span><span class="s2">&quot;image_name&quot;</span><span class="p">]</span>

            <span class="k">if</span> <span class="s2">&quot;profile&quot;</span> <span class="ow">in</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">]:</span>
                <span class="c1"># Load a specific profile for this provider</span>
                <span class="n">profile</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">][</span><span class="s2">&quot;profile&quot;</span><span class="p">]</span>
                <span class="n">provider_name</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">][</span><span class="s2">&quot;provider&quot;</span><span class="p">]</span>
                <span class="n">settings</span> <span class="o">=</span> <span class="n">load_settings</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">,</span> <span class="n">profile</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">provider_name</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">][</span><span class="s2">&quot;provider&quot;</span><span class="p">]</span>
                <span class="n">settings</span> <span class="o">=</span> <span class="n">compose</span><span class="p">[</span><span class="s2">&quot;upload&quot;</span><span class="p">][</span><span class="s2">&quot;settings&quot;</span><span class="p">]</span>
        <span class="k">except</span> <span class="ne">KeyError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="sa">f</span><span class="s1">&#39;Missing parameter </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s1">!&#39;</span><span class="p">})</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">provider</span> <span class="o">=</span> <span class="n">resolve_provider</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">)</span>
            <span class="k">if</span> <span class="s2">&quot;supported_types&quot;</span> <span class="ow">in</span> <span class="n">provider</span> <span class="ow">and</span> <span class="n">compose_type</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">provider</span><span class="p">[</span><span class="s2">&quot;supported_types&quot;</span><span class="p">]:</span>
                <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Type &quot;</span><span class="si">{</span><span class="n">compose_type</span><span class="si">}</span><span class="s1">&quot; is not supported by provider &quot;</span><span class="si">{</span><span class="n">provider_name</span><span class="si">}</span><span class="s1">&quot;!&#39;</span><span class="p">)</span>
            <span class="n">validate_settings</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">,</span> <span class="n">settings</span><span class="p">,</span> <span class="n">image_name</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)})</span>

    <span class="k">if</span> <span class="n">errors</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">build_id</span> <span class="o">=</span> <span class="n">start_build</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;DNFLOCK&quot;</span><span class="p">],</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;GITLOCK&quot;</span><span class="p">],</span>
                               <span class="n">branch</span><span class="p">,</span> <span class="n">blueprint_name</span><span class="p">,</span> <span class="n">compose_type</span><span class="p">,</span> <span class="n">test_mode</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">if</span> <span class="s2">&quot;Invalid compose type&quot;</span> <span class="ow">in</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">BAD_COMPOSE_TYPE</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">BUILD_FAILED</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>

    <span class="k">if</span> <span class="s2">&quot;upload&quot;</span> <span class="ow">in</span> <span class="n">compose</span><span class="p">:</span>
        <span class="n">upload_id</span> <span class="o">=</span> <span class="n">uuid_schedule_upload</span><span class="p">(</span>
            <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span>
            <span class="n">build_id</span><span class="p">,</span>
            <span class="n">provider_name</span><span class="p">,</span>
            <span class="n">image_name</span><span class="p">,</span>
            <span class="n">settings</span>
        <span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">upload_id</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>

    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">build_id</span><span class="o">=</span><span class="n">build_id</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_id</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_compose_queue"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_queue">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/queue&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">v1_compose_queue</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Return the status of the new and running queues</span>

<span class="sd">    **/api/v1/compose/queue**</span>

<span class="sd">      Return the status of the build queue. It includes information about the builds waiting,</span>
<span class="sd">      and the build that is running.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;new&quot;: [</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;45502a6d-06e8-48a5-a215-2b4174b3614b&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;glusterfs&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517362647.4570868,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.6&quot;</span>
<span class="sd">              },</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;6d292bd0-bec7-4825-8d7d-41ef9c3e4b73&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;kubernetes&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517362659.0034983,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.1&quot;</span>
<span class="sd">              }</span>
<span class="sd">            ],</span>
<span class="sd">            &quot;run&quot;: [</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;745712b2-96db-44c0-8014-fe925c35e795&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;glusterfs&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;RUNNING&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517362633.7965999,</span>
<span class="sd">                &quot;job_started&quot;: 1517362633.8001345,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.6&quot;,</span>
<span class="sd">                &quot;uploads&quot;: [</span>
<span class="sd">                    {</span>
<span class="sd">                        &quot;creation_time&quot;: 1568150660.524401,</span>
<span class="sd">                        &quot;image_name&quot;: &quot;glusterfs server&quot;,</span>
<span class="sd">                        &quot;image_path&quot;: null,</span>
<span class="sd">                        &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">                        &quot;settings&quot;: {</span>
<span class="sd">                            &quot;client_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;location&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;resource_group&quot;: &quot;group&quot;,</span>
<span class="sd">                            &quot;secret&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_account_name&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_container&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;subscription_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;tenant&quot;: &quot;need&quot;</span>
<span class="sd">                        },</span>
<span class="sd">                        &quot;status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                        &quot;uuid&quot;: &quot;21898dfd-9ac9-4e22-bb1d-7f12d0129e65&quot;</span>
<span class="sd">                    }</span>
<span class="sd">                ]</span>
<span class="sd">              }</span>
<span class="sd">            ]</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">queue_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span></div>

<div class="viewcode-block" id="v1_compose_finished"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_finished">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/finished&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">v1_compose_finished</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Return the list of finished composes</span>

<span class="sd">    **/api/v1/compose/finished**</span>

<span class="sd">      Return the details on all of the finished composes on the system.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;finished&quot;: [</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;70b84195-9817-4b8a-af92-45e380f39894&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;glusterfs&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;FINISHED&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517351003.8210032,</span>
<span class="sd">                &quot;job_started&quot;: 1517351003.8230415,</span>
<span class="sd">                &quot;job_finished&quot;: 1517359234.1003145,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.6&quot;</span>
<span class="sd">              },</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;e695affd-397f-4af9-9022-add2636e7459&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;glusterfs&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;FINISHED&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517362289.7193348,</span>
<span class="sd">                &quot;job_started&quot;: 1517362289.9751132,</span>
<span class="sd">                &quot;job_finished&quot;: 1517363500.1234567,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.6&quot;,</span>
<span class="sd">                &quot;uploads&quot;: [</span>
<span class="sd">                    {</span>
<span class="sd">                        &quot;creation_time&quot;: 1568150660.524401,</span>
<span class="sd">                        &quot;image_name&quot;: &quot;glusterfs server&quot;,</span>
<span class="sd">                        &quot;image_path&quot;: &quot;/var/lib/lorax/composer/results/e695affd-397f-4af9-9022-add2636e7459/disk.vhd&quot;,</span>
<span class="sd">                        &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">                        &quot;settings&quot;: {</span>
<span class="sd">                            &quot;client_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;location&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;resource_group&quot;: &quot;group&quot;,</span>
<span class="sd">                            &quot;secret&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_account_name&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_container&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;subscription_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;tenant&quot;: &quot;need&quot;</span>
<span class="sd">                        },</span>
<span class="sd">                        &quot;status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                        &quot;uuid&quot;: &quot;21898dfd-9ac9-4e22-bb1d-7f12d0129e65&quot;</span>
<span class="sd">                    }</span>
<span class="sd">                ]</span>
<span class="sd">              }</span>
<span class="sd">            ]</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">finished</span><span class="o">=</span><span class="n">build_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="s2">&quot;FINISHED&quot;</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span></div>

<div class="viewcode-block" id="v1_compose_failed"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_failed">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/failed&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">v1_compose_failed</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Return the list of failed composes</span>

<span class="sd">    **/api/v1/compose/failed**</span>

<span class="sd">      Return the details on all of the failed composes on the system.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;failed&quot;: [</span>
<span class="sd">               {</span>
<span class="sd">                &quot;id&quot;: &quot;8c8435ef-d6bd-4c68-9bf1-a2ef832e6b1a&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;http-server&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;FAILED&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517523249.9301329,</span>
<span class="sd">                &quot;job_started&quot;: 1517523249.9314211,</span>
<span class="sd">                &quot;job_finished&quot;: 1517523255.5623411,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.2&quot;,</span>
<span class="sd">                &quot;uploads&quot;: [</span>
<span class="sd">                    {</span>
<span class="sd">                        &quot;creation_time&quot;: 1568150660.524401,</span>
<span class="sd">                        &quot;image_name&quot;: &quot;http-server&quot;,</span>
<span class="sd">                        &quot;image_path&quot;: null,</span>
<span class="sd">                        &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">                        &quot;settings&quot;: {</span>
<span class="sd">                            &quot;client_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;location&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;resource_group&quot;: &quot;group&quot;,</span>
<span class="sd">                            &quot;secret&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_account_name&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_container&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;subscription_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;tenant&quot;: &quot;need&quot;</span>
<span class="sd">                        },</span>
<span class="sd">                        &quot;status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                        &quot;uuid&quot;: &quot;21898dfd-9ac9-4e22-bb1d-7f12d0129e65&quot;</span>
<span class="sd">                    }</span>
<span class="sd">                ]</span>
<span class="sd">              }</span>
<span class="sd">            ]</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">failed</span><span class="o">=</span><span class="n">build_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="s2">&quot;FAILED&quot;</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">))</span></div>

<div class="viewcode-block" id="v1_compose_status"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_status">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/status&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;uuids&#39;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">})</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/status/&lt;uuids&gt;&quot;</span><span class="p">)</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;uuids&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUIDs given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_compose_status</span><span class="p">(</span><span class="n">uuids</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Return the status of the listed uuids</span>

<span class="sd">    **/api/v1/compose/status/&lt;uuids&gt;[?blueprint=&lt;blueprint_name&gt;&amp;status=&lt;compose_status&gt;&amp;type=&lt;compose_type&gt;]**</span>

<span class="sd">      Return the details for each of the comma-separated list of uuids. A uuid of &#39;*&#39; will return</span>
<span class="sd">      details for all composes.</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;uuids&quot;: [</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;8c8435ef-d6bd-4c68-9bf1-a2ef832e6b1a&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;http-server&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;FINISHED&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517523644.2384307,</span>
<span class="sd">                &quot;job_started&quot;: 1517523644.2551234,</span>
<span class="sd">                &quot;job_finished&quot;: 1517523689.9864314,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.2&quot;</span>
<span class="sd">              },</span>
<span class="sd">              {</span>
<span class="sd">                &quot;id&quot;: &quot;45502a6d-06e8-48a5-a215-2b4174b3614b&quot;,</span>
<span class="sd">                &quot;blueprint&quot;: &quot;glusterfs&quot;,</span>
<span class="sd">                &quot;queue_status&quot;: &quot;FINISHED&quot;,</span>
<span class="sd">                &quot;job_created&quot;: 1517363442.188399,</span>
<span class="sd">                &quot;job_started&quot;: 1517363442.325324,</span>
<span class="sd">                &quot;job_finished&quot;: 1517363451.653621,</span>
<span class="sd">                &quot;version&quot;: &quot;0.0.6&quot;,</span>
<span class="sd">                &quot;uploads&quot;: [</span>
<span class="sd">                    {</span>
<span class="sd">                        &quot;creation_time&quot;: 1568150660.524401,</span>
<span class="sd">                        &quot;image_name&quot;: &quot;glusterfs server&quot;,</span>
<span class="sd">                        &quot;image_path&quot;: null,</span>
<span class="sd">                        &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">                        &quot;settings&quot;: {</span>
<span class="sd">                            &quot;client_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;location&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;resource_group&quot;: &quot;group&quot;,</span>
<span class="sd">                            &quot;secret&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_account_name&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;storage_container&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;subscription_id&quot;: &quot;need&quot;,</span>
<span class="sd">                            &quot;tenant&quot;: &quot;need&quot;</span>
<span class="sd">                        },</span>
<span class="sd">                        &quot;status&quot;: &quot;WAITING&quot;,</span>
<span class="sd">                        &quot;uuid&quot;: &quot;21898dfd-9ac9-4e22-bb1d-7f12d0129e65&quot;</span>
<span class="sd">                    }</span>
<span class="sd">                ]</span>
<span class="sd">              }</span>
<span class="sd">            ]</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">uuids</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="n">blueprint</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;blueprint&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
    <span class="n">status</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;status&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
    <span class="n">compose_type</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;type&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>

    <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">errors</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">if</span> <span class="n">uuids</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;*&#39;</span><span class="p">:</span>
        <span class="n">queue_status_dict</span> <span class="o">=</span> <span class="n">queue_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">queue_new</span> <span class="o">=</span> <span class="n">queue_status_dict</span><span class="p">[</span><span class="s2">&quot;new&quot;</span><span class="p">]</span>
        <span class="n">queue_running</span> <span class="o">=</span> <span class="n">queue_status_dict</span><span class="p">[</span><span class="s2">&quot;run&quot;</span><span class="p">]</span>
        <span class="n">candidates</span> <span class="o">=</span> <span class="n">queue_new</span> <span class="o">+</span> <span class="n">queue_running</span> <span class="o">+</span> <span class="n">build_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">candidates</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">uuid</span> <span class="ow">in</span> <span class="p">[</span><span class="n">n</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">uuids</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="p">)]:</span>
            <span class="n">details</span> <span class="o">=</span> <span class="n">uuid_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">uuid</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">details</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                <span class="n">errors</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_UUID</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> is not a valid build uuid&quot;</span> <span class="o">%</span> <span class="n">uuid</span><span class="p">})</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">candidates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">details</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">details</span> <span class="ow">in</span> <span class="n">candidates</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">blueprint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">details</span><span class="p">[</span><span class="s1">&#39;blueprint&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="n">blueprint</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="k">if</span> <span class="n">status</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">details</span><span class="p">[</span><span class="s1">&#39;queue_status&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="n">status</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="k">if</span> <span class="n">compose_type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">details</span><span class="p">[</span><span class="s1">&#39;compose_type&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="n">compose_type</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">details</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">uuids</span><span class="o">=</span><span class="n">results</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_compose_info"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_info">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/info&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;uuid&#39;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">})</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/info/&lt;uuid&gt;&quot;</span><span class="p">)</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_compose_info</span><span class="p">(</span><span class="n">uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Return detailed info about a compose</span>

<span class="sd">    **/api/v1/compose/info/&lt;uuid&gt;**</span>

<span class="sd">      Get detailed information about the compose. The returned JSON string will</span>
<span class="sd">      contain the following information:</span>

<span class="sd">        * id - The uuid of the comoposition</span>
<span class="sd">        * config - containing the configuration settings used to run Anaconda</span>
<span class="sd">        * blueprint - The depsolved blueprint used to generate the kickstart</span>
<span class="sd">        * commit - The (local) git commit hash for the blueprint used</span>
<span class="sd">        * deps - The NEVRA of all of the dependencies used in the composition</span>
<span class="sd">        * compose_type - The type of output generated (tar, iso, etc.)</span>
<span class="sd">        * queue_status - The final status of the composition (FINISHED or FAILED)</span>

<span class="sd">      Example::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;commit&quot;: &quot;7078e521a54b12eae31c3fd028680da7a0815a4d&quot;,</span>
<span class="sd">            &quot;compose_type&quot;: &quot;tar&quot;,</span>
<span class="sd">            &quot;config&quot;: {</span>
<span class="sd">              &quot;anaconda_args&quot;: &quot;&quot;,</span>
<span class="sd">              &quot;armplatform&quot;: &quot;&quot;,</span>
<span class="sd">              &quot;compress_args&quot;: [],</span>
<span class="sd">              &quot;compression&quot;: &quot;xz&quot;,</span>
<span class="sd">              &quot;image_name&quot;: &quot;root.tar.xz&quot;,</span>
<span class="sd">              ...</span>
<span class="sd">            },</span>
<span class="sd">            &quot;deps&quot;: {</span>
<span class="sd">              &quot;packages&quot;: [</span>
<span class="sd">                {</span>
<span class="sd">                  &quot;arch&quot;: &quot;x86_64&quot;,</span>
<span class="sd">                  &quot;epoch&quot;: &quot;0&quot;,</span>
<span class="sd">                  &quot;name&quot;: &quot;acl&quot;,</span>
<span class="sd">                  &quot;release&quot;: &quot;14.el7&quot;,</span>
<span class="sd">                  &quot;version&quot;: &quot;2.2.51&quot;</span>
<span class="sd">                }</span>
<span class="sd">              ]</span>
<span class="sd">            },</span>
<span class="sd">            &quot;id&quot;: &quot;c30b7d80-523b-4a23-ad52-61b799739ce8&quot;,</span>
<span class="sd">            &quot;queue_status&quot;: &quot;FINISHED&quot;,</span>
<span class="sd">            &quot;blueprint&quot;: {</span>
<span class="sd">              &quot;description&quot;: &quot;An example kubernetes master&quot;,</span>
<span class="sd">              ...</span>
<span class="sd">            },</span>
<span class="sd">            &quot;uploads&quot;: [</span>
<span class="sd">                {</span>
<span class="sd">                    &quot;creation_time&quot;: 1568150660.524401,</span>
<span class="sd">                    &quot;image_name&quot;: &quot;glusterfs server&quot;,</span>
<span class="sd">                    &quot;image_path&quot;: &quot;/var/lib/lorax/composer/results/c30b7d80-523b-4a23-ad52-61b799739ce8/disk.vhd&quot;,</span>
<span class="sd">                    &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">                    &quot;settings&quot;: {</span>
<span class="sd">                        &quot;client_id&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;location&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;resource_group&quot;: &quot;group&quot;,</span>
<span class="sd">                        &quot;secret&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;storage_account_name&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;storage_container&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;subscription_id&quot;: &quot;need&quot;,</span>
<span class="sd">                        &quot;tenant&quot;: &quot;need&quot;</span>
<span class="sd">                    },</span>
<span class="sd">                    &quot;status&quot;: &quot;FAILED&quot;,</span>
<span class="sd">                    &quot;uuid&quot;: &quot;21898dfd-9ac9-4e22-bb1d-7f12d0129e65&quot;</span>
<span class="sd">                }</span>
<span class="sd">            ]</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">info</span> <span class="o">=</span> <span class="n">uuid_info</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">uuid</span><span class="p">,</span> <span class="n">api</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">COMPOSE_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>

    <span class="k">if</span> <span class="n">info</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UNKNOWN_UUID</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> is not a valid build uuid&quot;</span> <span class="o">%</span> <span class="n">uuid</span><span class="p">}]),</span> <span class="mi">400</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="o">**</span><span class="n">info</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_compose_uploads_schedule"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_uploads_schedule">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/uploads/schedule&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;compose_uuid&#39;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">},</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/compose/uploads/schedule/&lt;compose_uuid&gt;&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;compose_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no compose UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_compose_uploads_schedule</span><span class="p">(</span><span class="n">compose_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Schedule an upload of a compose to a given cloud provider</span>

<span class="sd">    **POST /api/v1/uploads/schedule/&lt;compose_uuid&gt;**</span>

<span class="sd">      The body can specify either a pre-existing profile to use (as returned by</span>
<span class="sd">      `/uploads/providers`) or one-time use settings for the provider.</span>

<span class="sd">      Example with upload profile::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;image_name&quot;: &quot;My Image&quot;,</span>
<span class="sd">            &quot;provider&quot;: &quot;azure&quot;,</span>
<span class="sd">            &quot;profile&quot;: &quot;production-azure-settings&quot;</span>
<span class="sd">          }</span>

<span class="sd">      Example with upload settings::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;image_name&quot;: &quot;My Image&quot;,</span>
<span class="sd">            &quot;provider&quot;: &quot;azure&quot;,</span>
<span class="sd">            &quot;settings&quot;: {</span>
<span class="sd">              &quot;resource_group&quot;: &quot;SOMEBODY&quot;,</span>
<span class="sd">              &quot;storage_account_name&quot;: &quot;ONCE&quot;,</span>
<span class="sd">              &quot;storage_container&quot;: &quot;TOLD&quot;,</span>
<span class="sd">              &quot;location&quot;: &quot;ME&quot;,</span>
<span class="sd">              &quot;subscription_id&quot;: &quot;THE&quot;,</span>
<span class="sd">              &quot;client_id&quot;: &quot;WORLD&quot;,</span>
<span class="sd">              &quot;secret&quot;: &quot;IS&quot;,</span>
<span class="sd">              &quot;tenant&quot;: &quot;GONNA&quot;</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;572eb0d0-5348-4600-9666-14526ba628bb&quot;</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">compose_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="n">parsed</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_json</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">parsed</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">MISSING_POST</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Missing POST body&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">image_name</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;image_name&quot;</span><span class="p">]</span>
        <span class="n">provider_name</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;provider&quot;</span><span class="p">]</span>
        <span class="k">if</span> <span class="s2">&quot;profile&quot;</span> <span class="ow">in</span> <span class="n">parsed</span><span class="p">:</span>
            <span class="c1"># Load a specific profile for this provider</span>
            <span class="n">profile</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;profile&quot;</span><span class="p">]</span>
            <span class="n">settings</span> <span class="o">=</span> <span class="n">load_settings</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">,</span> <span class="n">profile</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">settings</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;settings&quot;</span><span class="p">]</span>
    <span class="k">except</span> <span class="ne">KeyError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="sa">f</span><span class="s1">&#39;Missing parameter </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s1">!&#39;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">compose_type</span> <span class="o">=</span> <span class="n">uuid_status</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">compose_uuid</span><span class="p">)[</span><span class="s2">&quot;compose_type&quot;</span><span class="p">]</span>
        <span class="n">provider</span> <span class="o">=</span> <span class="n">resolve_provider</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">)</span>
        <span class="k">if</span> <span class="s2">&quot;supported_types&quot;</span> <span class="ow">in</span> <span class="n">provider</span> <span class="ow">and</span> <span class="n">compose_type</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">provider</span><span class="p">[</span><span class="s2">&quot;supported_types&quot;</span><span class="p">]:</span>
            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
                <span class="sa">f</span><span class="s1">&#39;Type &quot;</span><span class="si">{</span><span class="n">compose_type</span><span class="si">}</span><span class="s1">&quot; is not supported by provider &quot;</span><span class="si">{</span><span class="n">provider_name</span><span class="si">}</span><span class="s1">&quot;!&#39;</span>
            <span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">upload_id</span> <span class="o">=</span> <span class="n">uuid_schedule_upload</span><span class="p">(</span>
            <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span>
            <span class="n">compose_uuid</span><span class="p">,</span>
            <span class="n">provider_name</span><span class="p">,</span>
            <span class="n">image_name</span><span class="p">,</span>
            <span class="n">settings</span>
        <span class="p">)</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}]),</span> <span class="mi">400</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_id</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_compose_uploads_delete"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_compose_uploads_delete">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/delete&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">},</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/delete/&lt;upload_uuid&gt;&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no upload UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_compose_uploads_delete</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Delete an upload and disassociate it from its compose</span>

<span class="sd">    **DELETE /api/v1/upload/delete/&lt;upload_uuid&gt;**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;572eb0d0-5348-4600-9666-14526ba628bb&quot;</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">uuid_remove_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">)</span>
        <span class="n">delete_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">error</span><span class="p">)}])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_uuid</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_upload_info"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_upload_info">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/info&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">})</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/info/&lt;upload_uuid&gt;&quot;</span><span class="p">)</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_upload_info</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Returns information about a given upload</span>

<span class="sd">    **GET /api/v1/upload/info/&lt;upload_uuid&gt;**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload&quot;: {</span>
<span class="sd">              &quot;creation_time&quot;: 1565620940.069004,</span>
<span class="sd">              &quot;image_name&quot;: &quot;My Image&quot;,</span>
<span class="sd">              &quot;image_path&quot;: &quot;/var/lib/lorax/composer/results/b6218e8f-0fa2-48ec-9394-f5c2918544c4/disk.vhd&quot;,</span>
<span class="sd">              &quot;provider_name&quot;: &quot;azure&quot;,</span>
<span class="sd">              &quot;settings&quot;: {</span>
<span class="sd">                &quot;resource_group&quot;: &quot;SOMEBODY&quot;,</span>
<span class="sd">                &quot;storage_account_name&quot;: &quot;ONCE&quot;,</span>
<span class="sd">                &quot;storage_container&quot;: &quot;TOLD&quot;,</span>
<span class="sd">                &quot;location&quot;: &quot;ME&quot;,</span>
<span class="sd">                &quot;subscription_id&quot;: &quot;THE&quot;,</span>
<span class="sd">                &quot;client_id&quot;: &quot;WORLD&quot;,</span>
<span class="sd">                &quot;secret&quot;: &quot;IS&quot;,</span>
<span class="sd">                &quot;tenant&quot;: &quot;GONNA&quot;</span>
<span class="sd">              },</span>
<span class="sd">              &quot;status&quot;: &quot;FAILED&quot;,</span>
<span class="sd">              &quot;uuid&quot;: &quot;b637c411-9d9d-4279-b067-6c8d38e3b211&quot;</span>
<span class="sd">            }</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">upload</span> <span class="o">=</span> <span class="n">get_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">)</span><span class="o">.</span><span class="n">summary</span><span class="p">()</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">error</span><span class="p">)}])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload</span><span class="o">=</span><span class="n">upload</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_upload_log"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_upload_log">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/log&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">})</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/log/&lt;upload_uuid&gt;&quot;</span><span class="p">)</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_upload_log</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Returns an upload&#39;s log</span>

<span class="sd">    **GET /api/v1/upload/log/&lt;upload_uuid&gt;**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;b637c411-9d9d-4279-b067-6c8d38e3b211&quot;,</span>
<span class="sd">            &quot;log&quot;: &quot;&lt; PLAY [localhost] &gt;...&quot;</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">upload</span> <span class="o">=</span> <span class="n">get_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">error</span><span class="p">)}])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_uuid</span><span class="p">,</span> <span class="n">log</span><span class="o">=</span><span class="n">upload</span><span class="o">.</span><span class="n">upload_log</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_upload_reset"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_upload_reset">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/reset&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">},</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/reset/&lt;upload_uuid&gt;&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_upload_reset</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Reset an upload so it can be attempted again</span>

<span class="sd">    **POST /api/v1/upload/reset/&lt;upload_uuid&gt;**</span>

<span class="sd">      Optionally pass in a new image name and/or new settings.</span>

<span class="sd">      Example request::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;image_name&quot;: &quot;My renamed image&quot;,</span>
<span class="sd">            &quot;settings&quot;: {</span>
<span class="sd">              &quot;resource_group&quot;: &quot;ROLL&quot;,</span>
<span class="sd">              &quot;storage_account_name&quot;: &quot;ME&quot;,</span>
<span class="sd">              &quot;storage_container&quot;: &quot;I&quot;,</span>
<span class="sd">              &quot;location&quot;: &quot;AIN&#39;T&quot;,</span>
<span class="sd">              &quot;subscription_id&quot;: &quot;THE&quot;,</span>
<span class="sd">              &quot;client_id&quot;: &quot;SHARPEST&quot;,</span>
<span class="sd">              &quot;secret&quot;: &quot;TOOL&quot;,</span>
<span class="sd">              &quot;tenant&quot;: &quot;IN&quot;</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;c75d5d62-9d26-42fc-a8ef-18bb14679fc7&quot;</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="n">parsed</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_json</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
    <span class="n">image_name</span> <span class="o">=</span> <span class="n">parsed</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;image_name&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">parsed</span> <span class="k">else</span> <span class="kc">None</span>
    <span class="n">settings</span> <span class="o">=</span> <span class="n">parsed</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;settings&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">parsed</span> <span class="k">else</span> <span class="kc">None</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">reset_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">,</span> <span class="n">image_name</span><span class="p">,</span> <span class="n">settings</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">error</span><span class="p">)}])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_uuid</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_upload_cancel"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_upload_cancel">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/cancel&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">},</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/cancel/&lt;upload_uuid&gt;&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;upload_uuid&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no UUID given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_upload_cancel</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Cancel an upload that is either queued or in progress</span>

<span class="sd">    **DELETE /api/v1/upload/cancel/&lt;upload_uuid&gt;**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true,</span>
<span class="sd">            &quot;upload_id&quot;: &quot;037a3d56-b421-43e9-9935-c98350c89996&quot;</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">upload_uuid</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">cancel_upload</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">upload_uuid</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">error</span><span class="p">)}])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">upload_id</span><span class="o">=</span><span class="n">upload_uuid</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_upload_providers"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_upload_providers">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/providers&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">v1_upload_providers</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Return the information about all upload providers, including their</span>
<span class="sd">    display names, expected settings, and saved profiles. Refer to the</span>
<span class="sd">    `resolve_provider` function.</span>

<span class="sd">    **GET /api/v1/upload/providers**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;providers&quot;: {</span>
<span class="sd">              &quot;azure&quot;: {</span>
<span class="sd">                &quot;display&quot;: &quot;Azure&quot;,</span>
<span class="sd">                &quot;profiles&quot;: {</span>
<span class="sd">                  &quot;default&quot;: {</span>
<span class="sd">                    &quot;client_id&quot;: &quot;example&quot;,</span>
<span class="sd">                    ...</span>
<span class="sd">                  }</span>
<span class="sd">                },</span>
<span class="sd">                &quot;settings-info&quot;: {</span>
<span class="sd">                  &quot;client_id&quot;: {</span>
<span class="sd">                    &quot;display&quot;: &quot;Client ID&quot;,</span>
<span class="sd">                    &quot;placeholder&quot;: &quot;&quot;,</span>
<span class="sd">                    &quot;regex&quot;: &quot;&quot;,</span>
<span class="sd">                    &quot;type&quot;: &quot;string&quot;</span>
<span class="sd">                  },</span>
<span class="sd">                  ...</span>
<span class="sd">                },</span>
<span class="sd">                &quot;supported_types&quot;: [&quot;vhd&quot;]</span>
<span class="sd">              },</span>
<span class="sd">              ...</span>
<span class="sd">            }</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">ucfg</span> <span class="o">=</span> <span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">]</span>

    <span class="n">provider_names</span> <span class="o">=</span> <span class="n">list_providers</span><span class="p">(</span><span class="n">ucfg</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">get_provider_info</span><span class="p">(</span><span class="n">provider_name</span><span class="p">):</span>
        <span class="n">provider</span> <span class="o">=</span> <span class="n">resolve_provider</span><span class="p">(</span><span class="n">ucfg</span><span class="p">,</span> <span class="n">provider_name</span><span class="p">)</span>
        <span class="n">provider</span><span class="p">[</span><span class="s2">&quot;profiles&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">load_profiles</span><span class="p">(</span><span class="n">ucfg</span><span class="p">,</span> <span class="n">provider_name</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">provider</span>

    <span class="n">providers</span> <span class="o">=</span> <span class="p">{</span><span class="n">provider_name</span><span class="p">:</span> <span class="n">get_provider_info</span><span class="p">(</span><span class="n">provider_name</span><span class="p">)</span>
                 <span class="k">for</span> <span class="n">provider_name</span> <span class="ow">in</span> <span class="n">provider_names</span><span class="p">}</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">providers</span><span class="o">=</span><span class="n">providers</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_providers_save"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_providers_save">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/providers/save&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;POST&quot;</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">v1_providers_save</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;Save provider settings as a profile for later use</span>

<span class="sd">    **POST /api/v1/upload/providers/save**</span>

<span class="sd">      Example request::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;provider&quot;: &quot;azure&quot;,</span>
<span class="sd">            &quot;profile&quot;: &quot;my-profile&quot;,</span>
<span class="sd">            &quot;settings&quot;: {</span>
<span class="sd">              &quot;resource_group&quot;: &quot;SOMEBODY&quot;,</span>
<span class="sd">              &quot;storage_account_name&quot;: &quot;ONCE&quot;,</span>
<span class="sd">              &quot;storage_container&quot;: &quot;TOLD&quot;,</span>
<span class="sd">              &quot;location&quot;: &quot;ME&quot;,</span>
<span class="sd">              &quot;subscription_id&quot;: &quot;THE&quot;,</span>
<span class="sd">              &quot;client_id&quot;: &quot;WORLD&quot;,</span>
<span class="sd">              &quot;secret&quot;: &quot;IS&quot;,</span>
<span class="sd">              &quot;tenant&quot;: &quot;GONNA&quot;</span>
<span class="sd">            }</span>
<span class="sd">          }</span>

<span class="sd">      Saving to an existing profile will overwrite it.</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">parsed</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_json</span><span class="p">(</span><span class="n">cache</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">parsed</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">MISSING_POST</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Missing POST body&quot;</span><span class="p">}]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">provider_name</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;provider&quot;</span><span class="p">]</span>
        <span class="n">profile</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;profile&quot;</span><span class="p">]</span>
        <span class="n">settings</span> <span class="o">=</span> <span class="n">parsed</span><span class="p">[</span><span class="s2">&quot;settings&quot;</span><span class="p">]</span>
    <span class="k">except</span> <span class="ne">KeyError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="sa">f</span><span class="s1">&#39;Missing parameter </span><span class="si">{</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="s1">!&#39;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">save_settings</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">,</span> <span class="n">profile</span><span class="p">,</span> <span class="n">settings</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>

<div class="viewcode-block" id="v1_providers_delete"><a class="viewcode-back" href="../../../pylorax.api.html#pylorax.api.v1.v1_providers_delete">[docs]</a><span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/providers/delete&quot;</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;provider_name&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;profile&quot;</span><span class="p">:</span> <span class="s2">&quot;&quot;</span><span class="p">},</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@v1_api</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/upload/providers/delete/&lt;provider_name&gt;/&lt;profile&gt;&quot;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;DELETE&quot;</span><span class="p">])</span>
<span class="nd">@checkparams</span><span class="p">([(</span><span class="s2">&quot;provider_name&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no provider name given&quot;</span><span class="p">),</span> <span class="p">(</span><span class="s2">&quot;profile&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="s2">&quot;no profile given&quot;</span><span class="p">)])</span>
<span class="k">def</span> <span class="nf">v1_providers_delete</span><span class="p">(</span><span class="n">provider_name</span><span class="p">,</span> <span class="n">profile</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Delete a provider&#39;s profile settings</span>

<span class="sd">    **DELETE /api/v1/upload/providers/delete/&lt;provider_name&gt;/&lt;profile&gt;**</span>

<span class="sd">      Example response::</span>

<span class="sd">          {</span>
<span class="sd">            &quot;status&quot;: true</span>
<span class="sd">          }</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="kc">None</span> <span class="ow">in</span> <span class="p">(</span><span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">provider_name</span><span class="p">),</span> <span class="n">VALID_API_STRING</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">profile</span><span class="p">)):</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">INVALID_CHARS</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="s2">&quot;Invalid characters in API path&quot;</span><span class="p">}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">]),</span> <span class="mi">400</span>

    <span class="k">try</span><span class="p">:</span>
        <span class="n">delete_profile</span><span class="p">(</span><span class="n">api</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;COMPOSER_CFG&quot;</span><span class="p">][</span><span class="s2">&quot;upload&quot;</span><span class="p">],</span> <span class="n">provider_name</span><span class="p">,</span> <span class="n">profile</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">error</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;id&quot;</span><span class="p">:</span> <span class="n">UPLOAD_ERROR</span><span class="p">,</span> <span class="s2">&quot;msg&quot;</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)}</span>
        <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="p">[</span><span class="n">error</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>
</pre></div>

           </div>
           
          </div>
          <footer>
  

  <hr/>

  <div role="contentinfo">
    <p>
        &copy; Copyright 2018, Red Hat, Inc.

    </p>
  </div>
  Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/rtfd/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. 

</footer>

        </div>
      </div>

    </section>

  </div>
  


  <script type="text/javascript">
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script>

  
  
    
   

</body>
</html>