The Foreman Projects is a complete lifecycle management tool for physical and virtual servers. https://www.theforeman.org/
This python package is intended to provide a simple and flexible python interface for interacting with the Foreman API v2.
This package uses the requests module to communicate with the Foreman API.
This project is intended to be Free and Open Source Software (FOSS)
It is distributed with the GPLv3 Liscense foud here: https://www.gnu.org/licenses/gpl-3.0.en.html
The project provides relies on the following modules being installed:
- requests
- future (for python 2.7 support)
The main object used to interact with Foreman is a "record". A record is a json representation of a Foreman object which is used by the API's various REST enpoints. Examples of the types or records available are an environment, a host, a subnet, etc. When making API calls the user is often required to supply a record or will retrieve a record as the response.
The Foreman API does not implement all of the API endpoints in a uniform way. This class implements an abstraction layer which provides a unified model for performing CRUD operations against the API. It's constructor requires a username, password, url, and an boolean representing whether or not to verify SSL certificates which is useful when utilizing a self signed cert.
All of the CRUD operations translate into API calls made by the make_api_call function.
All of the CRUD operations require the same parameter set:
-
record_type - The type of the Foreman object the user wants to interact with (eg. subnet)
-
minimal_record_state - The JSON payload expected for the API call or returned by the API call.
The make_api_call function requires that the user supply an endpoint, method, a dict object representing the json arguments, and headers. (Some of these terms are discussed later)
An API call can fail in two ways, in either case an Exception object will be thrown:
-
An internal error occurs
This can happen when the user misconfigured the ForemanApiWrapper and the internal python code suffered an exception
For example a 400 exception because the user tried to request a URL that did not exist
-
A server side error occurs
This can happen if the remote Foreman server encounters a problem.
For example the server returns a 500 or 300 level error message.
In both cases the ForemanApiWrapper will try to construct a descriptive ForemanApiCallException by extracting any information that may be available from the underlying request response and attaching it to the custom exception as fields.
In order to unify the interfaces presented by the various API endpoints a mapping was required. Two mapping files keep track of the data translations which need to happen based on the REST endpoint and the record type. These are loaded when the class is instantiated and can be modified as needed.
This object will encapsulate the error that occurred while making an api call against a remote Foreman API.
The object will display the following fields.
-
endpoint
This is the url that the exception was thrown from
-
method
This is the HTTP method used to request the endpoint
-
results
This is the result object returned from the underlying requests python module.
The result object has a content attribute which contains the actual json returned by the server
-
arguments
This is a deserialized representation of the json that was sent to the API endpoint in the request body
-
headers
This is a dict object containing the HTTP headers that were sent to the API endpoint during the request body
This class implements an idempotent interface for managing Foreman objects (records). It allows the user to specify whether records are present or absent using a "state model".
In this model, the user specifies a "desired state" for a record (which can be "present" or "absent") and a "minimal record representation" (an API compatible JSON string) which describes the record in question. Using the CRUD functionality of the ForemanApiWrapper, the ApiStateEnforcer will interrogate the API to ensure that the "minimal record" is represented on the Foreman server. In other words it will make sure a record exists (or does not exist) with the specified fields. Any additional fields will be ignored; hence the term "minimal".
Note: The minimal representation must contain either the name or the id of the record in question.
This functionality is encapsulate within the ensure_state function.
The function requires the following parameters:
-
record_type - The type of the Foreman object the user wants to interact with (eg. subnet)
-
desiredState - This can be "present" or "absent" to denote whether or not the minimal state should exist
-
minimal_record - The JSON payload expected for the API call or returned by the API call.
The function will return a RecordModificationReceipt which will host the following fields:
- changed - a boolean representing whether or not a Write/Update was performed
- reason - a string explaining why the change was made
- minimal_record - the minimal record supplied by the user
- desired_state - the desired state supplied by the user
- actual_record - the record returned by the API if a Write/Update occurred
- original_record - the record returned by the API when a Read occurred (before any Write/Update)