<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GU aka Matteo Guadrini</title>
    <description>The latest articles on DEV Community by GU aka Matteo Guadrini (@matteoguadrini).</description>
    <link>https://dev.to/matteoguadrini</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F172620%2F0bdce094-e733-44d3-82b8-a4df51b923bc.png</url>
      <title>DEV Community: GU aka Matteo Guadrini</title>
      <link>https://dev.to/matteoguadrini</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/matteoguadrini"/>
    <language>en</language>
    <item>
      <title>How to create own Python project in 5 minutes like a pro</title>
      <dc:creator>GU aka Matteo Guadrini</dc:creator>
      <pubDate>Fri, 20 Dec 2024 15:50:27 +0000</pubDate>
      <link>https://dev.to/matteoguadrini/how-to-create-own-python-project-in-5-minutes-22bg</link>
      <guid>https://dev.to/matteoguadrini/how-to-create-own-python-project-in-5-minutes-22bg</guid>
      <description>&lt;h2&gt;
  
  
  Why Python package?
&lt;/h2&gt;

&lt;p&gt;Python supports all types of execution; you can run Python code directly into a shell, or put your code into file and run later.&lt;/p&gt;

&lt;p&gt;Sometimes to start a new Python project is very hard; Write a script? Write a module? Write a package?&lt;/p&gt;

&lt;p&gt;The best choice is micropiecies pattern: write a script, so rewrite that in a module and so rewrite in a package.&lt;/p&gt;

&lt;p&gt;This pattern permits you to don't re-inventing the wheel every day and you reuse the code in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python package structure
&lt;/h2&gt;

&lt;p&gt;Python package has this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pkg
├── __init__.py
├── module1.py
└── subpkg
    ├── __init__.py
    ├── __main__.py
    └── module2.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The folder &lt;code&gt;pkg&lt;/code&gt; is a package, because contains &lt;code&gt;__init__.py&lt;/code&gt; module. Also the folder &lt;code&gt;subpkg&lt;/code&gt; is a package; is a subpackage of &lt;code&gt;pkg&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;module1.py&lt;/code&gt; and &lt;code&gt;module2.py&lt;/code&gt; are a modules of their packages.&lt;br&gt;
The &lt;code&gt;__main__.py&lt;/code&gt; module permits the execution of package.&lt;/p&gt;
&lt;h2&gt;
  
  
  Only here? Other things?
&lt;/h2&gt;

&lt;p&gt;If you will become a Python developer, then you use other usually tools.&lt;/p&gt;

&lt;p&gt;In order, you follow this steps every piece of code you write:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write Python code into your package&lt;/li&gt;
&lt;li&gt;Track your modifications&lt;/li&gt;
&lt;li&gt;Test all code that you write&lt;/li&gt;
&lt;li&gt;Put your code into environment that you test it&lt;/li&gt;
&lt;li&gt;Push your code in remote repository&lt;/li&gt;
&lt;li&gt;Build your package for distribution&lt;/li&gt;
&lt;li&gt;Upload your package into &lt;a href="https://pypi.org/" rel="noopener noreferrer"&gt;PyPi&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Pipelines
&lt;/h2&gt;

&lt;p&gt;Every change in your code, may introduces possible bugs. To discard this, every time we need test own package in the correct environment.&lt;/p&gt;

&lt;p&gt;To do this, some tools are needed over Python itself, like &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;make&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Documentation, license and other common files
&lt;/h2&gt;

&lt;p&gt;It is not enough to simply create a Python package and make it immediately available to everyone. You also have to think about how to document it, explain it briefly to other people, license it and explain how to integrate into the project.&lt;/p&gt;

&lt;p&gt;This requires developing files like &lt;em&gt;README&lt;/em&gt;, &lt;em&gt;LICENSE&lt;/em&gt;, &lt;em&gt;CODE_OF_CONDUCT&lt;/em&gt; and &lt;em&gt;CONTRIBUTING&lt;/em&gt;.&lt;br&gt;
Maybe adding a &lt;em&gt;CHANGELOG&lt;/em&gt; to keep and have others keep track of the changes made to each version.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create project in a few minutes
&lt;/h2&gt;

&lt;p&gt;To realize all parts of a Python project, serves some hours or days.&lt;br&gt;
But exists a tool for scaffolding your Python project: &lt;a href="https://github.com/MatteoGuadrini/psp" rel="noopener noreferrer"&gt;&lt;code&gt;psp&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After we follow the &lt;a href="https://psp.readthedocs.io/en/latest/#installation" rel="noopener noreferrer"&gt;installation instructions&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu ~] sudo apt install -y python3 python3-pip git curl
[test@ubuntu ~] curl -L https://github.com/MatteoGuadrini/psp/releases/download/v0.1.0/psp.deb -o psp.deb
[test@ubuntu ~] sudo dpkg -i psp.deb
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu ~] psp
Welcome to PSP (Python Scaffolding Projects): 0.1.0
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Name of Python project: app
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want to create a virtual environment? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want to start git repository? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Select git remote provider: Gitlab
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Username of Gitlab: test_user
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want unit &lt;span class="nb"&gt;test &lt;/span&gt;files? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Install dependencies: flask
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Select documention generator: MKDocs
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want to configure tox? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Select remote CI provider: CircleCI
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want create common files? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Select license: Gnu Public License
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want to &lt;span class="nb"&gt;install &lt;/span&gt;dependencies to publish on pypi? Yes
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Do you want to create a Dockerfile and Containerfile? Yes
&lt;span class="go"&gt;Python project `app` created at app
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, check the Python project that has been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu ~] ls -lah app
total 88K
drwxrwxr-x  9 test   test    440 Dec 20 14:48 .
drwxrwxrwt 29 root   root    680 Dec 20 14:49 ..
drwxrwxr-x  2 test   test     60 Dec 20 14:47 .circleci
drwxrwxr-x  7 test   test    200 Dec 20 14:47 .git
-rw-rw-r--  1 test   test    381 Dec 20 14:47 .gitignore
drwxrwxr-x  4 test   test     80 Dec 20 14:47 .gitlab
-rw-rw-r--  1 test   test    127 Dec 20 14:48 CHANGES.md
-rw-rw-r--  1 test   test   5.4K Dec 20 14:48 CODE_OF_CONDUCT.md
-rw-rw-r--  1 test   test   1.1K Dec 20 14:48 CONTRIBUTING.md
-rw-rw-r--  1 test   test    190 Dec 20 14:48 Containerfile
-rw-rw-r--  1 test   test    190 Dec 20 14:48 Dockerfile
-rw-rw-r--  1 test   test    35K Dec 20 14:48 LICENSE.md
-rw-rw-r--  1 test   test    697 Dec 20 14:48 Makefile
-rw-rw-r--  1 test   test    177 Dec 20 14:48 README.md
drwxrwxr-x  2 test   test     60 Dec 20 14:47 docs
-rw-rw-r--  1 test   test     19 Dec 20 14:47 mkdocs.yml
-rw-rw-r--  1 test   test    819 Dec 20 14:48 pyproject.toml
-rw-rw-r--  1 test   test     66 Dec 20 14:47 requirements.txt
drwxrwxr-x  2 test   test     80 Dec 20 14:47 tests
-rw-rw-r--  1 test   test    213 Dec 20 14:47 tox.ini
drwxrwxr-x  2 test   test     80 Dec 20 14:46 app
drwxrwxr-x  5 test   test    140 Dec 20 14:46 venv
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Start develop the package
&lt;/h3&gt;

&lt;p&gt;Start develop the package that &lt;code&gt;psp&lt;/code&gt; command has created for our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu ~] cd app/ &amp;amp;&amp;amp; ls -lh app/
total 8.0K
-rw-rw-r-- 1 test test 162 Dec 20 14:46 __init__.py
-rw-rw-r-- 1 test test 204 Dec 20 14:46 __main__.py
[test@ubuntu ~] vim app/core.py
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;p&amp;gt;Wow, this is my app!&amp;lt;/p&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, import our &lt;code&gt;hello_world&lt;/code&gt; function into &lt;code&gt;__main__.py&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] vim app/__main__.py
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#! /usr/bin/env python3
# -*- encoding: utf-8 -*-
# vim: se ts=4 et syn=python:
# Generated by psp (https://github.com/MatteoGuadrini/psp)
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.__init__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;__version__&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;app &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;__version__&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run our package
&lt;/h3&gt;

&lt;p&gt;You have write a simple, but organized and powerful package that is ready to production and distribution.&lt;/p&gt;

&lt;p&gt;Test our package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] venv/bin/python -m app
app 0.0.1
 * Serving Flask app 'app.core'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with watchdog (inotify)
app 0.0.1
 * Debugger is active!
 * Debugger PIN: 352-398-739
127.0.0.1 - - [20/Dec/2024 15:21:27] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/Dec/2024 15:21:28] "GET /favicon.ico HTTP/1.1" 404 -
^C
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And result is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9wjkkxdv096oncwj9os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9wjkkxdv096oncwj9os.png" alt="flask" width="367" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Execute unit tests on package
&lt;/h3&gt;

&lt;p&gt;Now tests also the Python code on the package, throught &lt;code&gt;tests&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] ls -l tests
total 8
-rw-rw-r-- 1 test test 141 Dec 20 14:59 __init__.py
-rw-rw-r-- 1 test test 465 Dec 20 14:59 test_app.py
[test@ubuntu app] venv/bin/python3 -m unittest
Test all app successfully!
&lt;/span&gt;&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Save our works
&lt;/h3&gt;

&lt;p&gt;Now you can save the development of your web app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] git status
On branch master

No commits yet

Untracked files:
&lt;/span&gt;&lt;span class="gp"&gt;  (use "git add &amp;lt;file&amp;gt;&lt;/span&gt;...&lt;span class="s2"&gt;" to include in what will be committed)
&lt;/span&gt;&lt;span class="go"&gt;        .circleci/
        .gitignore
        .gitlab/
        CHANGES.md
        CODE_OF_CONDUCT.md
        CONTRIBUTING.md
        Containerfile
        Dockerfile
        LICENSE.md
        Makefile
        README.md
        app/
        docs/
        mkdocs.yml
        pyproject.toml
        requirements.txt
        tests/
        tox.ini

nothing added to commit but untracked files present (use "git add" to track)
[test@ubuntu app] git add -A &amp;amp;&amp;amp; git commit -m "chore: hello app"
[master (root-commit) 96db65f] chore: hello app
 23 files changed, 1126 insertions(+)
 create mode 100644 .circleci/config.yml
 create mode 100644 .gitignore
 create mode 100644 .gitlab/issue_templates/bug.md
 create mode 100644 .gitlab/issue_templates/feature.md
 create mode 100644 .gitlab/merge_request_templates/merge.md
 create mode 100644 CHANGES.md
 create mode 100644 CODE_OF_CONDUCT.md
 create mode 100644 CONTRIBUTING.md
 create mode 100644 Containerfile
 create mode 100644 Dockerfile
 create mode 100644 LICENSE.md
 create mode 100644 Makefile
 create mode 100644 README.md
 create mode 100644 app/__init__.py
 create mode 100644 app/__main__.py
 create mode 100644 app/core.py
 create mode 100644 docs/index.md
 create mode 100644 mkdocs.yml
 create mode 100644 pyproject.toml
 create mode 100644 requirements.txt
 create mode 100644 tests/__init__.py
 create mode 100644 tests/test_app.py
 create mode 100644 tox.ini
[test@ubuntu app] git log
&lt;/span&gt;&lt;span class="gp"&gt;author: test_user &amp;lt;*******&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;Date:   Fri Dec 20 15:35:10 2024 +0100

    chore: hello app
(END)
[test@ubuntu app] git push --set-upstream origin master &amp;amp;&amp;amp; git push
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test environment
&lt;/h3&gt;

&lt;p&gt;Simulate with &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;docker&lt;/a&gt; your production environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] docker build . -t app:0.0.1
STEP 1/6: FROM python:3
STEP 2/6: COPY app /app/app
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cf0db0178706
&lt;span class="go"&gt;STEP 3/6: COPY pyproject.toml /app
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;363ca0249ca4
&lt;span class="go"&gt;STEP 4/6: WORKDIR /app
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;6167fc048a28
&lt;span class="go"&gt;STEP 5/6: RUN pip install .
Processing /app
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;baf94c942fb9
&lt;span class="go"&gt;STEP 6/6: CMD [ 'python', '-m', 'app' ]
COMMIT app:0.0.1
&lt;/span&gt;&lt;span class="gp"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;e8afe180c81d
&lt;span class="go"&gt;Successfully tagged localhost/app:0.0.1
e8afe180c81d0897173885edf4abaf8c92e60e0fbd9548d1f5a40711085421c1
[test@ubuntu app] docker run -it --rm localhost/app:0.0.1 python -m app
app 0.0.1
 * Serving Flask app 'app.core'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with stat
app 0.0.1
 * Debugger is active!
 * Debugger PIN: 115-031-071
^C
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the result is the same:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9wjkkxdv096oncwj9os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9wjkkxdv096oncwj9os.png" alt="flask" width="367" height="145"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Build the pipeline with make
&lt;/h3&gt;

&lt;p&gt;Now, after the next development, you can use the pipeline with &lt;code&gt;Makefile&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] make clean test run
rm -fr build/
rm -fr dist/
rm -fr .eggs/
find . -name '*.egg-info' -exec rm -fr {} +
find . -name '*.egg' -exec rm -f {} +
find . -name '*.pyc' -exec rm -f {} +
find . -name '*.pyo' -exec rm -f {} +
find . -name '*~' -exec rm -f {} +
find . -name '__pycache__' -exec rm -fr {} +
venv/bin/python3 -m unittest
Test all app successfully!
&lt;/span&gt;&lt;span class="c"&gt;.
&lt;/span&gt;&lt;span class="go"&gt;----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
venv/bin/python3 -m app
app 0.0.1
 * Serving Flask app 'app.core'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with watchdog (inotify)
app 0.0.1
 * Debugger is active!
 * Debugger PIN: 352-398-739
^C
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Publish the package on PyPi
&lt;/h3&gt;

&lt;p&gt;Now, if you want, you are ready to publish youp Python package on PyPi:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;[test@ubuntu app] python -m build &amp;amp;&amp;amp; python -m twine upload dist/*
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools
  - wheel
* Getting build dependencies for sdist...
running egg_info
writing app.egg-info/PKG-INFO
writing dependency_links to app.egg-info/dependency_links.txt
writing requirements to app.egg-info/requires.txt
writing top-level names to app.egg-info/top_level.txt
reading manifest file 'app.egg-info/SOURCES.txt'
adding license file 'LICENSE.md'
writing manifest file 'app.egg-info/SOURCES.txt'
* Building sdist...
running sdist
running egg_info
writing app.egg-info/PKG-INFO
writing dependency_links to app.egg-info/dependency_links.txt
writing requirements to app.egg-info/requires.txt
writing top-level names to app.egg-info/top_level.txt
reading manifest file 'app.egg-info/SOURCES.txt'
adding license file 'LICENSE.md'
writing manifest file 'app.egg-info/SOURCES.txt'
running check
creating app-0.0.1
creating app-0.0.1/app
creating app-0.0.1/app.egg-info
creating app-0.0.1/tests
copying files to app-0.0.1...
&lt;/span&gt;&lt;span class="gp"&gt;copying LICENSE.md -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1
&lt;span class="gp"&gt;copying README.md -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1
&lt;span class="gp"&gt;copying pyproject.toml -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1
&lt;span class="gp"&gt;copying app/__init__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app
&lt;span class="gp"&gt;copying app/__main__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app
&lt;span class="gp"&gt;copying app/core.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app
&lt;span class="gp"&gt;copying app.egg-info/PKG-INFO -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="gp"&gt;copying app.egg-info/SOURCES.txt -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="gp"&gt;copying app.egg-info/dependency_links.txt -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="gp"&gt;copying app.egg-info/requires.txt -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="gp"&gt;copying app.egg-info/top_level.txt -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="gp"&gt;copying tests/test_app.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/tests
&lt;span class="gp"&gt;copying app.egg-info/SOURCES.txt -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;app-0.0.1/app.egg-info
&lt;span class="go"&gt;Writing app-0.0.1/setup.cfg
Creating tar archive
removing 'app-0.0.1' (and everything under it)
* Building wheel from sdist
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - setuptools
  - wheel
* Getting build dependencies for wheel...
running egg_info
writing app.egg-info/PKG-INFO
writing dependency_links to app.egg-info/dependency_links.txt
writing requirements to app.egg-info/requires.txt
writing top-level names to app.egg-info/top_level.txt
reading manifest file 'app.egg-info/SOURCES.txt'
adding license file 'LICENSE.md'
writing manifest file 'app.egg-info/SOURCES.txt'
* Building wheel...
running bdist_wheel
running build
running build_py
creating build/lib/app
&lt;/span&gt;&lt;span class="gp"&gt;copying app/__init__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/lib/app
&lt;span class="gp"&gt;copying app/__main__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/lib/app
&lt;span class="gp"&gt;copying app/core.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/lib/app
&lt;span class="go"&gt;running egg_info
writing app.egg-info/PKG-INFO
writing dependency_links to app.egg-info/dependency_links.txt
writing requirements to app.egg-info/requires.txt
writing top-level names to app.egg-info/top_level.txt
reading manifest file 'app.egg-info/SOURCES.txt'
adding license file 'LICENSE.md'
writing manifest file 'app.egg-info/SOURCES.txt'
installing to build/bdist.linux-x86_64/wheel
running install
running install_lib
creating build/bdist.linux-x86_64/wheel
creating build/bdist.linux-x86_64/wheel/app
&lt;/span&gt;&lt;span class="gp"&gt;copying build/lib/app/__init__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/bdist.linux-x86_64/wheel/./app
&lt;span class="gp"&gt;copying build/lib/app/__main__.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/bdist.linux-x86_64/wheel/./app
&lt;span class="gp"&gt;copying build/lib/app/core.py -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;build/bdist.linux-x86_64/wheel/./app
&lt;span class="go"&gt;running install_egg_info
Copying app.egg-info to build/bdist.linux-x86_64/wheel/./app-0.0.1-py3.12.egg-info
running install_scripts
creating build/bdist.linux-x86_64/wheel/app-0.0.1.dist-info/WHEEL
creating '/tmp/app/dist/.tmp-bf8qnjot/app-0.0.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it
adding 'app/__init__.py'
adding 'app/__main__.py'
adding 'app/core.py'
adding 'app-0.0.1.dist-info/LICENSE.md'
adding 'app-0.0.1.dist-info/METADATA'
adding 'app-0.0.1.dist-info/WHEEL'
adding 'app-0.0.1.dist-info/top_level.txt'
adding 'app-0.0.1.dist-info/RECORD'
removing build/bdist.linux-x86_64/wheel
Successfully built app-0.0.1.tar.gz and app-0.0.1-py3-none-any.whl
Uploading distributions to https://upload.pypi.org/legacy/
Uploading app-0.0.1-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 18.2/18.2 kB • 00:00 • 11.3 MB/s
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;psp&lt;/code&gt; creates for you other utils configurations; &lt;a href="https://tox.wiki/en/4.19.0/index.html" rel="noopener noreferrer"&gt;tox&lt;/a&gt; to create test pipelines. &lt;a href="https://www.mkdocs.org/" rel="noopener noreferrer"&gt;mkdocs&lt;/a&gt; or &lt;a href="https://www.sphinx-doc.org/en/master/" rel="noopener noreferrer"&gt;sphinx&lt;/a&gt; to create documentation. A README.md file to describe your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conslusion
&lt;/h2&gt;

&lt;p&gt;In less than five minutes, you have created a Python project where the development of the package itself is the only thing you have to worry about. &lt;/p&gt;

&lt;p&gt;Tools used on this article:&lt;br&gt;
&lt;code&gt;psp&lt;/code&gt;: &lt;a href="https://github.com/MatteoGuadrini/psp" rel="noopener noreferrer"&gt;repository&lt;/a&gt; -- &lt;a href="https://psp.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;br&gt;
&lt;code&gt;git&lt;/code&gt;: &lt;a href="https://github.com/git/git" rel="noopener noreferrer"&gt;repository&lt;/a&gt; -- &lt;a href="https://git-scm.com/doc" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;br&gt;
&lt;code&gt;docker&lt;/code&gt;: &lt;a href="https://github.com/docker" rel="noopener noreferrer"&gt;repository&lt;/a&gt; -- &lt;a href="https://docs.docker.com/engine/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;br&gt;
&lt;code&gt;make&lt;/code&gt;: &lt;a href="https://git.savannah.gnu.org/gitweb/?p=coreutils.git" rel="noopener noreferrer"&gt;repository&lt;/a&gt; -- &lt;a href="https://www.gnu.org/software/make/manual/make.html" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;br&gt;
&lt;code&gt;python&lt;/code&gt;: &lt;a href="https://github.com/python" rel="noopener noreferrer"&gt;repository&lt;/a&gt; -- &lt;a href="https://docs.python.org/3/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Building cross-platform application with Powershell and Apache CouchDB</title>
      <dc:creator>GU aka Matteo Guadrini</dc:creator>
      <pubDate>Thu, 01 Aug 2019 15:11:16 +0000</pubDate>
      <link>https://dev.to/matteoguadrini/building-cross-platform-application-with-powershell-and-apache-couchdb-539f</link>
      <guid>https://dev.to/matteoguadrini/building-cross-platform-application-with-powershell-and-apache-couchdb-539f</guid>
      <description>&lt;h1&gt;
  
  
  CouchDB Database
&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://couchdb.apache.org/" rel="noopener noreferrer"&gt;Apache CouchDB&lt;/a&gt; is a no-sql database, implemented on the HTTP and JSON API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantage
&lt;/h2&gt;

&lt;p&gt;This type of database is structured in a &lt;code&gt;database -&amp;gt; documents -&amp;gt; revision_document -&amp;gt; data&lt;/code&gt;. This allows for versioned documents. But it is not the only point of advantage; the replication in CouchDB is really the killer feature that sets it apart from other databases.&lt;/p&gt;

&lt;h1&gt;
  
  
  (Power)Shell
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/powershell/" rel="noopener noreferrer"&gt;Powershell&lt;/a&gt; is a shell developed in .NET core, and is a shell with typed objects. PowerShell promises to revolutionize the world of system management and&lt;br&gt;
command-line shells. From its object-based pipelines to its administrator focus to its enormous reach into other Microsoft management technologies, PowerShell drastically improves the productivity of administrators and power users alike.&lt;/p&gt;
&lt;h2&gt;
  
  
  PSCouchDB module
&lt;/h2&gt;

&lt;p&gt;To interface with CouchDB, you need to install a powershell module: &lt;a href="https://matteoguadrini.github.io/PSCouchDB/" rel="noopener noreferrer"&gt;PSCouchDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Installation is simple; or use git (&lt;a href="https://pscouchdb.readthedocs.io/en/latest/intro.html#installation" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://github.com/MatteoGuadrini/PSCouchDB.git&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PSCouchDB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# for Windows&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/Y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PSCouchDB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;Windir&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;\System32\WindowsPowerShell\v1.0\Modules&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# for Unix&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PSCouchDB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/usr/local/share/powershell/Modules&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or &lt;a href="https://www.powershellgallery.com/packages/PSCouchDB" rel="noopener noreferrer"&gt;PowershellGallery&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PSCouchDB&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test pscouchdb module
&lt;/h3&gt;

&lt;p&gt;With this, you can discover all cmdlets available to work with CouchDB in PSCouchDB module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Search-CouchDBHelp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Pattern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Demonstration
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/232696" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fasciinema.org%2Fa%2F232696.svg" alt="asciicast" width="2030" height="1007"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Configure CouchDB cluster
&lt;/h1&gt;

&lt;p&gt;The time has come to configure our database. We begin to decide which type of cluster will be our database.&lt;br&gt;
For a simple configuration, as in our case, we choose a single node cluster.&lt;/p&gt;
&lt;h2&gt;
  
  
  Admin
&lt;/h2&gt;

&lt;p&gt;But first, you need to create an admin user who can write and read from the database. (Without an admin, anyone can write and read from various databases; refer to the &lt;a href="https://docs.couchdb.org/en/stable/intro/security.html#the-admin-party" rel="noopener noreferrer"&gt;Admin Party&lt;/a&gt; guide.)&lt;br&gt;
Create a &lt;em&gt;password&lt;/em&gt; and &lt;em&gt;admin&lt;/em&gt; user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$pwd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConvertTo-SecureString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-AsPlainText&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-CouchDBAdmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Userid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Password&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$pwd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test admin user has been created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-CouchDBAdmin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin:password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable cluster
&lt;/h2&gt;

&lt;p&gt;Now, enable our single cluster mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Enable-CouchDBCluster&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SingleNode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin:password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify that cluster has been created, verifying that he created the three databases: &lt;strong&gt;_global_changes&lt;/strong&gt;, &lt;strong&gt;_replicator&lt;/strong&gt;, &lt;strong&gt;_users&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Get-CouchDBDatabase&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a database for test
&lt;/h2&gt;

&lt;p&gt;We create a test database to verify that everything is working properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;New-CouchDBDatabase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin:password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Create application
&lt;/h1&gt;

&lt;p&gt;Applications in general solve a real problem. In this case, let us imagine that we must survey the hardware of our company. We need an application that every few minutes takes information from clients on Active Director and puts it in a database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simple machine inventory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a database
&lt;/h3&gt;

&lt;p&gt;Let's start by creating the database that will host the machine information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;New-CouchDBDatabase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin:password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a get function
&lt;/h3&gt;

&lt;p&gt;Let's start with editing the file called &lt;em&gt;HardwareInventory.ps1&lt;/em&gt;, with this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Get-ComputerInventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$Authorization&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;# Create an Active Directory session&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;New-PSSession&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_domain_controller.local"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Import-PSSession&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ActiveDirectory&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="c"&gt;# Get all computer&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$AllComputers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-ADComputer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DNSHostName&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$AllComputers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DNSHostName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c"&gt;# Test connection of computer&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Quiet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="c"&gt;# Select various info&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ComputerHW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-CimInstance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Win32_ComputerSystem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Manufacturer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="n"&gt;NumberOfProcessors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;Expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TotalPhysicalMemory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1GB&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"TotalPhysicalMemoryGB"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ComputerCPU'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;CimInstance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;win32_processor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DeviceID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nx"&gt;Manufacturer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nx"&gt;NumberOfCores&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nx"&gt;NumberOfLogicalProcessors&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ComputerDisks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;CimInstance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Win32_LogicalDisk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DriveType=3"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DeviceID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="nx"&gt;VolumeName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                   &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;Expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1GB&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"SizeGB"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MM&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dd&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;yyyy_HH_mm_ss&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="c"&gt;# Write on database&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nx"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Get&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;CouchDBDocument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Authorization&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Authorization&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;Set-CouchDBDocument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Revision&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-CouchDBDocument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_rev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-Replace&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;New-CouchDBDocument&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$info&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Get-PSSession&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Remove-PSSession&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this function, we can take the basic information of each machine in our domain via WMI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$info = @{}
$info.Add('ComputerHW', (Get-CimInstance -Class Win32_ComputerSystem -ComputerName $ComputerName |
            select Manufacturer,
                   Model,
                   NumberOfProcessors,
                   @{Expression={$_.TotalPhysicalMemory / 1GB};Label="TotalPhysicalMemoryGB"}))
$info.Add('ComputerCPU', (Get-CimInstance win32_processor -ComputerName $ComputerName |
            select DeviceID,
                   Name,
                   Manufacturer,
                   NumberOfCores,
                   NumberOfLogicalProcessors))
$info.Add('ComputerDisks', (Get-CimInstance -Class Win32_LogicalDisk -Filter "DriveType=3" -ComputerName $ComputerName |
            select DeviceID,
                   VolumeName,
                   @{Expression={$_.Size / 1GB};Label="SizeGB"}))
$info.Add("timestamp", (Get-Date -f MM-dd-yyyy_HH_mm_ss))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and write in database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Write on database
if (Get-CouchDBDocument -Database hw_inventory -Document $ComputerName -ErrorAction SilentlyContinue -Authorization $Authorization) {
    Set-CouchDBDocument -Database hw_inventory -Document $ComputerName -Data $info -Revision $(Get-CouchDBDocument -Database hw_inventory -Document $ComputerName)._rev -Replace
} else {
    New-CouchDBDocument -Database hw_inventory -Document $ComputerName -Data $info
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a find function
&lt;/h3&gt;

&lt;p&gt;Once we memorize the data, we would also need to look for them in some way; then we have to create a function always inside our file &lt;em&gt;HardwareInventory.ps1&lt;/em&gt; that can search the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find computer into inventory&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Find-ComputerInventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mandatory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Computername&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$docs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Find-CouchDBDocuments&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hw_inventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Selector&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"_id"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Operator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".*&lt;/span&gt;&lt;span class="nv"&gt;$Computername&lt;/span&gt;&lt;span class="s2"&gt;.*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Fields&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;ComputerHW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;ComputerCPU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;ComputerDisks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$docs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;docs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function allows you to search for the name of the machine and extract the data we are interested in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prepare functions
&lt;/h3&gt;

&lt;p&gt;At this point, we save and include our file in the &lt;em&gt;profile.ps1&lt;/em&gt; of all users of the machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="s2"&gt;". path_of_file/Hardware.ps1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$PsHome&lt;/span&gt;&lt;span class="n"&gt;\Profile.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use and schedule functions
&lt;/h3&gt;

&lt;p&gt;Now it's time to schedule everything every hour in order to collect the first data, with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# if use a powershell 6 or high, use pwsh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;powershell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Get-ComputerInventory -Authorization admin:password"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Find a machine
&lt;/h3&gt;

&lt;p&gt;Let's wait a couple of hours and look for a car to see if everything is working properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Find-ComputerInventory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ComputerName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;machine1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In 10 minutes we created a machine inventory application in powershell that interfaces to CouchDB, in complete safety.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/powershell/scripting/overview?view=powershell-6" rel="noopener noreferrer"&gt;Powershell docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.couchdb.org/en/stable/" rel="noopener noreferrer"&gt;CouchDB docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pscouchdb.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;PSCouchDB docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/MatteoGuadrini/PSCouchDB" rel="noopener noreferrer"&gt;PSCouchDB github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pscouchdb.readthedocs.io/en/latest/support.html#donations" rel="noopener noreferrer"&gt;Donations&lt;/a&gt;&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>nosql</category>
      <category>database</category>
      <category>shell</category>
    </item>
    <item>
      <title>Implement an open source backup-restore system.</title>
      <dc:creator>GU aka Matteo Guadrini</dc:creator>
      <pubDate>Thu, 20 Jun 2019 15:26:10 +0000</pubDate>
      <link>https://dev.to/matteoguadrini/implement-an-open-source-backup-restore-system-4cpo</link>
      <guid>https://dev.to/matteoguadrini/implement-an-open-source-backup-restore-system-4cpo</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;There are multiple open source backup/restore solutions, but almost all have an agent/server approach.&lt;/p&gt;

&lt;p&gt;The disadvantage of such an approach is that the consumption of hardware resources exists on both the client and server side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;rsync&lt;/strong&gt;, is a very simple tool with many very useful options. Unfortunately, this utility does not provide a backup/restore method, but only synchronization from point A to point B.&lt;/p&gt;

&lt;p&gt;However, a somewhat more complex logic can be implemented on it so that multiple backups can be managed, maintaining a sort of historicity.&lt;br&gt;
At this point, rsync becomes the core of something much more complex.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://matteoguadrini.github.io/Butterfly-Backup/" rel="noopener noreferrer"&gt;Butterfly Backup&lt;/a&gt; is a rsync wrapper, which increases its capacity, becoming a real backup/restore/archive tool. &lt;em&gt;Butterfly Backup is a simple command line wrapper of rsync for complex task, written in python.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a few simple steps, without repository configurations, particular settings and third-party software or plugins, you can implement an automatic enterprise backup/restore/archive system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;Such as? In four steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) INSTALLATION&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/MatteoGuadrini/Butterfly-Backup.git
&lt;span class="nb"&gt;cd &lt;/span&gt;Butterfly-Backup
&lt;span class="nb"&gt;sudo &lt;/span&gt;python3 setup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2) EDIT LIST OF COMPUTER/SERVER UNDER BACKUP&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; /mnt/san/bck_list
server01.local
server02
10.0.0.1
192.168.2.42
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3) DEPLOY CONFIG SSH KEY&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bb config &lt;span class="nt"&gt;--new&lt;/span&gt;
bb config &lt;span class="nt"&gt;--deploy&lt;/span&gt; server01.local
bb config &lt;span class="nt"&gt;--deploy&lt;/span&gt; server02
bb config &lt;span class="nt"&gt;--deploy&lt;/span&gt; 10.0.0.1
bb config &lt;span class="nt"&gt;--deploy&lt;/span&gt; 192.168.2.42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4) SETUP CRONTAB&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CMDBB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bb backup --list /mnt/san/bck_list --destination /mnt/san --data User Config --type Unix"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"00 12 * * * &lt;/span&gt;&lt;span class="nv"&gt;$CMDBB&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | crontab -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Et Voilà!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In 5 minutes, you have implemented an automatic backup system that saves the User folders and configuration folders (&lt;code&gt;/etc&lt;/code&gt;) of four servers, every 12:00 PM, every day.&lt;/p&gt;

&lt;p&gt;All the backups performed can be consulted in a catalog that is easy to read and consult, in this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bb list &lt;span class="nt"&gt;--catalog&lt;/span&gt; /mnt/san
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Sometimes the simplest solution is the best possible choice.&lt;/p&gt;

&lt;p&gt;For more information on this tool, follow the links below:&lt;/p&gt;

&lt;p&gt;WEBSITE: &lt;a href="https://matteoguadrini.github.io/Butterfly-Backup/" rel="noopener noreferrer"&gt;https://matteoguadrini.github.io/Butterfly-Backup/&lt;/a&gt;&lt;br&gt;
GITHUB: &lt;a href="https://github.com/MatteoGuadrini/Butterfly-Backup" rel="noopener noreferrer"&gt;https://github.com/MatteoGuadrini/Butterfly-Backup&lt;/a&gt;&lt;br&gt;
DOCS: &lt;a href="https://butterfly-backup.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;https://butterfly-backup.readthedocs.io/en/latest/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bash</category>
      <category>python</category>
      <category>butterflybackup</category>
    </item>
    <item>
      <title>Welcome Butterfly Backup</title>
      <dc:creator>GU aka Matteo Guadrini</dc:creator>
      <pubDate>Tue, 28 May 2019 08:53:02 +0000</pubDate>
      <link>https://dev.to/matteoguadrini/welcome-butterfly-backup-34k2</link>
      <guid>https://dev.to/matteoguadrini/welcome-butterfly-backup-34k2</guid>
      <description>&lt;h1&gt;
  
  
  What is Butterfly Backup
&lt;/h1&gt;

&lt;p&gt;Butterfly Backup (BB) is a simple wrapper of rsync written in python;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use it?
&lt;/h2&gt;

&lt;p&gt;Because it is simple and very effective, as it catalogs the backups performed (and archived).&lt;/p&gt;

&lt;p&gt;BB is a simple tool, born from a very clear need: to make backups without having agents that slow down the machine and to have catalogs for the interrogation by operators in case of restore.&lt;/p&gt;

&lt;p&gt;Thanks to an active community, BB has arrived at version 1.5, but 2.0 is in development.&lt;br&gt;
Every contribution is welcome!&lt;/p&gt;

&lt;p&gt;site: &lt;a href="https://matteoguadrini.github.io/Butterfly-Backup/" rel="noopener noreferrer"&gt;https://matteoguadrini.github.io/Butterfly-Backup/&lt;/a&gt;&lt;br&gt;
docs: &lt;a href="https://butterfly-backup.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;https://butterfly-backup.readthedocs.io/en/latest/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>backup</category>
    </item>
  </channel>
</rss>
