DEV Community

GU aka Matteo Guadrini
GU aka Matteo Guadrini

Posted on • Updated on

Building cross-platform application with Powershell and Apache CouchDB

CouchDB Database

Apache CouchDB is a no-sql database, implemented on the HTTP and JSON API.

Advantage

This type of database is structured in a database -> documents -> revision_document -> data. 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.

(Power)Shell

Powershell is a shell developed in .NET core, and is a shell with typed objects. PowerShell promises to revolutionize the world of system management and
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.

PSCouchDB module

To interface with CouchDB, you need to install a powershell module: PSCouchDB.

Installation is simple; or use git (documentation):

git clone https://github.com/MatteoGuadrini/PSCouchDB.git
cd PSCouchDB
# for Windows
copy /Y PSCouchDB %Windir%\System32\WindowsPowerShell\v1.0\Modules
# for Unix
cp -var PSCouchDB /usr/local/share/powershell/Modules

or PowershellGallery:

Install-Module -Name PSCouchDB 

Test pscouchdb module

With this, you can discover all cmdlets available to work with CouchDB in PSCouchDB module.

Search-CouchDBHelp -Pattern .

Demonstration

asciicast

Configure CouchDB cluster

The time has come to configure our database. We begin to decide which type of cluster will be our database.
For a simple configuration, as in our case, we choose a single node cluster.

Admin

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 Admin Party guide.)
Create a password and admin user:

$pwd = "password" | ConvertTo-SecureString -AsPlainText -Force
New-CouchDBAdmin -Userid admin -Password $pwd

Test admin user has been created:

Get-CouchDBAdmin -Authorization admin:password

Enable cluster

Now, enable our single cluster mode:

Enable-CouchDBCluster -SingleNode -Authorization admin:password

Verify that cluster has been created, verifying that he created the three databases: _global_changes, _replicator, _users

Get-CouchDBDatabase

Create a database for test

We create a test database to verify that everything is working properly:

New-CouchDBDatabase -Database test -Authorization admin:password

Create application

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.

Simple machine inventory

Create a database

Let's start by creating the database that will host the machine information:

New-CouchDBDatabase -Database hw_inventory -Authorization admin:password

Create a get function

Let's start with editing the file called HardwareInventory.ps1, with this function:

function Get-ComputerInventory ($Authorization) {
    # Create an Active Directory session
    $session = New-PSSession -ComputerName "your_domain_controller.local"
    Import-PSSession -Session $session -module ActiveDirectory
    # Get all computer
    $AllComputers = Get-ADComputer -Filter * -Properties DNSHostName
    foreach ($ComputerName in $AllComputers.DNSHostName) {
        $info = @{}
        # Test connection of computer
        if (Test-Connection $ComputerName -Count 1 -Quiet) {
            # Select various 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))
            # 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
            }
        }
    }
    Get-PSSession | Remove-PSSession
}

With this function, we can take the basic information of each machine in our domain via WMI:

$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))

and write in database:

# 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
}

Create a find function

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 HardwareInventory.ps1 that can search the database:

# Find computer into inventory
function Find-ComputerInventory () {
    param(
        [Parameter(mandatory=$true)]
        [string] $Computername
    )
    $docs = Find-CouchDBDocuments -Database hw_inventory -Selector "_id" -Operator regex -Value ".*$Computername.*" -Fields _id,ComputerHW,ComputerCPU,ComputerDisks,timestamp
    $docs.docs
}

This function allows you to search for the name of the machine and extract the data we are interested in.

Prepare functions

At this point, we save and include our file in the profile.ps1 of all users of the machine:

". path_of_file/Hardware.ps1" >> $PsHome\Profile.ps1

Use and schedule functions

Now it's time to schedule everything every hour in order to collect the first data, with this command:

# if use a powershell 6 or high, use pwsh
powershell -Command "Get-ComputerInventory -Authorization admin:password"

Find a machine

Let's wait a couple of hours and look for a car to see if everything is working properly:

Find-ComputerInventory -ComputerName machine1

Conclusion

In 10 minutes we created a machine inventory application in powershell that interfaces to CouchDB, in complete safety.

References

Powershell docs
CouchDB docs
PSCouchDB docs
PSCouchDB github

Donations

Top comments (0)