= RubyQA Design Doc
:Author: Tristan Ancelet
:Email: tristanancelet@yahoo.com
:Date: 2024/06/09
:Revision: 1.0
:doctype: book
:toc: left

== Introduction
=== What is this project?
This project is a ruby based QA framwork to handle gathering & organizing the information to be able to easily provide an API for tests to be done against the built linux system

=== What does it QA?
This project allows the developer/engineer to design their own test cases. These can cover anything that is build & can be queried from the CLI (disk partitions, network interface settings, etc)

== Framework Design
To help in making tests more accessible this project will be based specifically on OOP concepts. 

There will be multiple objects at play each providing a different utility & purpose:

* xref:manager[Manager]
* xref:host[Host]
* xref:test[Test]
* xref:resource[Resource]

Each object provides different API for being able to gather information & reference information gathered from the system in question.

[[manager]]
=== Manager
xref:manager_class[Full Class]

The Manager object is a aggragate object handling the creation & running of new tests. It provides the ability to define new tests and provide the test code via a block statement to return a boolean if the test passed or failed

[source,ruby]
----
manager = Manager.new
manager.new_test('test-name', :opt_var => "val") do |data|
   <test-code-here>
end
----

in the new_test method you will be able to provide filter arguments such as :site, :keyname, etc. that can be used to filter what tests may be run against a host.

For a general description, the Manager is the object that glues all of the other objects together, and helps provide context to the tests by providing them access to the Host object and if needed allows them to run arbitrary commands on teh remote machine.

[[host]]
=== Host 
xref:host_class[Full Class]

The Host is an object that provides API for being able to run commands (via ssh/net::ssh on the remote system and provides the output to be processed by a local object or test.

This will also (with the help of facter) store the facts of the remote machine (os, disks, interfaces, etc) to be used in tests and otherwise.

This will also allow for extending the class by providing it "Resources" (a class that provides commands to be run and then will handle serializing the information into a object format for use in tests)

[source,ruby]
----
host.new_resource("name", ObjectClass)
----

[[test]]
=== Test
xref:test_class[Full Class]

This is just an object meant to provide some abstraction & filtering of tests based off of metadata present from the developer.

It holds the metadata (name, options) & the test proc that is used for handling the tests
[source,ruby]
----
ManagerObj.new_test("test-name", :opt_var => "val") do |metadata|
  #<code>
end
----

[[resource]]
=== Resource
xref:resource_class[Full Class]

This is an abstract object meant to handle providing the Host object with the necessary commands to be run on the host OS & to accept the output to serialize the information recieved into an easy-to-use format for use in a test

[source,ruby]
----
class Resource
  attr_reader :metadata
  def initailize (host, metadata = {})
    @host = host
    @metadata = metadata
    @data = Hash.new
  end
  def exec
    output, return_code = @host.exec(@gather_command)
    if return_code == 0
      load(output)
    else
      raise "Something"
    end
  end
end

class NewResource < Resource
   def initialize (host, metadata = {})
     super host, metadata
     @gather_command = "<command>"
   end

   def load(command_output)
     <serialize-data>
   end
end
----

== Lifecycle 
=== Setting up your Project
In the project your main file would do the following (in order):

* Create your Manager object (global is best)
* Define your host (hostname, ip (if not resolvable by DNS), username, password (optional if you don't want to store it in code), and any other metadata you want stored about the host)
* Define your tests (best to do so in an exernal file 'tests.rb')

.Example main.rb
[source,ruby]
----
#!/usr/bin/env ruby

## add the project path to $LOAD_PATH (to allow for easier requires)
$LOAD_PATH << __dir__

## Require main RubyQA file (will require other necessary modules)
## needed since the Manager must be defined before your tests
require 'rubyqa'
include RubyQA
$Manager = Manager.new

host = Host.new(
	:hostname => "testhostname.localdomain",
	:ip       => "192.168.25.23",
	#:port     => 22,
	:username => "user",
	#:password => "Pass123!",
	#:site     => "SITE A",
	#:cluster  => true,
)

## Load your tests so that the $Manager can be updated (will error out otherwise)
require 'tests.rb'


$Manager.add_host(host)
$Manager.run_tests
$Manager.print_report
----

