Package: crayon-cloudiq-sdk
Crayon CloudIQ SDK for PythonThis project is an SDK for Crayon's CloudIQ API that can be used in Python
scripts and applications. Provides a simple interface to authenticate with
the API using Oauth2. It can be used to create tenants, create licensing subscriptions,
and monitor billing. Anything that can be done in the Cloud-IQ portal can be automated
using this package.Includes several pre-configured data schema and API methods.
Custom blocks of data can be posted to the API as Python dictionaries. REST methods:
GET, POST, PATCH, PUT, and DELETE can be called with an API endpoint and data dictionary as arguments.InstallationInstall the crayon-cloudiq-sdk package with the following command:pip install crayon-cloudiq-sdkSetupHow to Create Cloud-IQ API Client CredentialsLogin to Cloud IQChoose Manage -> API Management from the top menuPress the + Add Client buttonChoose a name of the clientChoose Resource Flow as the authentication typeSave the Client ID and the Client SecretUsageCreate a new python scriptImport the CloudIQ classfrom cloudiq import CloudIQInitialize an instance of the CloudIQ class with valid user credentials:from cloudiq import CloudIQ

CLIENT_ID = xxxxxxx-xxxx-xxxx-xxxx-xxxxxx
CLIENT_SECRET = xxxxxxx-xxxx-xxxx-xxxx-xxxxxx
USERNAME = "example@example.com"
PASSWORD = "Password123456"

crayon_api = CloudIQ(CLIENT_ID,CLIENT_SECRET,USERNAME,PASSWORD)The prefered way of importing credentials is through ENV variables.from os import getenv
from cloudiq import CloudIQ

CLIENT_ID = getenv('CLIENT_ID')
CLIENT_SECRET = getenv('CLIENT_SECRET')
USERNAME = getenv('CLOUDIQ_USER')
PASSWORD = getenv('CLOUDIQ_PW')

crayon_api = CloudIQ(CLIENT_ID,CLIENT_SECRET,USERNAME,PASSWORD)ENV variables can be set using various methods including injection if using containers and pipelines or through a secrets manager such as Azure KeyVault. To set them on a local system using bash run the following commands:export CLIENT_ID="xxxxxxx-xxxx-xxxx-xxxx-xxxxxx"
export CLIENT_SECRET="xxxxxxx-xxxx-xxxx-xxxx-xxxxxx"
export USERNAME="example@example.com"
export PASSWORD="Password123456"An alternative method is to use a config.ini file containing the credentials and retrieve them using the configparser module.import configparser
from cloudiq import CloudIQ

# Parse configuration file
try:
	config = configparser.ConfigParser()
	config.read('config.ini')
	ID = config['CRAYON_API']['ID']
	SECRET = config['CRAYON_API']['SECRET']
	USER = config['CRAYON_API']['USER']
	PASS = config['CRAYON_API']['PASS']
except configparser.Error:
	print("Configuration Error...config.ini not found")
	exit()
except KeyError:
	print("Configuration Error...configuration not found in config.ini")
	exit()

crayon_api = CloudIQ(CLIENT_ID,CLIENT_SECRET,USERNAME,PASSWORD)See examples folder for authentication demos using configparser, ENV variables, and Azure DevOps PipelinesReturned DataData that is returned by the API is saved into a response object (except for getToken and validateToken). The response object contains values such as the status_code, headers, cookies, and the text returned by the API call.To return the json data from the response use response.json() class methodTo return the status code use the response.statuscode variableAll successful API calls either return200 OK,201 Created, or204 No ContentMost error responses also provide a detailed error message in JSON formIf you receive a 500 error, the data Schema payload is most likely the issue. It may be formatted incorrectly or missing required fields.Remember to handle error statuses when writing automationsError Handling Example using Return Status Code:response = crayon_api.me()

if(int(response.status_code) == 200):
	# Handle JSON data
    print(response.json())
else:
	# Handle Error
	print(response.status_code)
	exit(1)For a full explanation of the fields within a response object, please review the information in the following links:Official Requests.Response class documentation:https://docs.python-requests.org/en/latest/api/#requests.ResponseW3 Schools:https://www.w3schools.com/PYTHON/ref_requests_response.aspExample callsMake an unauthenticated test ping to the APIresponse = crayon_api.ping()
print(response,json())Get information about the currently authenticated userresponse = crayon_api.me()
print(response.json())Make a raw GET request:# retrieves all products in the Azure Active Directory product family within Org 123456
params = {
	'OrganizationId': 123456,
	'Include.ProductFamilyNames': 'Azure Active Directory'
}
# make a GET request to https://api.crayon.com/api/v1/AgreementProducts
response = crayon_api.get("https://api.crayon.com/api/v1/AgreementProducts",params)
print(response.json())Data can be sent to the API as a standard Python dictionary objectRetrieve a valid authorization token:response = crayon_api.getToken()
print(response)Create a tenant using the CustomerTenantDetailed schema:# Set Unique Tenant Variables
tenant_name = "tenant_name"
domain_prefix = "domain_prefix"

# Initialize Tenant and Agreement objects
tenant = crayon_api.CustomerTenantDetailed(
	tenant_name=tenant_name,
	domain_prefix=domain_prefix,
	org_id=111111,
	org_name="Fake Org",
	invoice_profile_id=80408, # Default
	contact_firstname="First",
	contact_lastname="Last",
	contact_email="email@example.com",
	contact_phone="5555555555",
	address_firstname="First",
	address_lastname="Last",
	address_address="75 NoWhere Lane",
	address_city="Boston",
	address_countrycode="US",
	address_region="MA",
	address_zipcode="02109"
)

agreement = crayon_api.CustomerTenantAgreement(
	firstname="First",
	lastname="Last",
	phone_number="5555555555",
	email="email@example.com"
)

#Create New Tenant
new_tenant = crayon_api.createTenant(tenant.tenant)
print(new_tenant.json())

# Agree to Microsoft Customer Agreement
tenant_id = new_tenant["Tenant"]["Id"]  
agreement = crayon_api.createTenantAgreement(tenant_id,agreement.agreement)
print(agreement.json())Buy a Microsoft license for a tenant using the SubscriptionDetailed schema:tenant_id=123456

# Create Subscription objects
azure_subscription = crayon_api.SubscriptionDetailed(
	name="Azure P2 Subscription",
	tenant_id=tenant_id,
	part_number="CFQ7TTC0LFK5:0001",
	quantity=1,
	billing_cycle=1,
	duration="P1M"
)

# Create Azure P2 Subscription
subscription = crayon_api.createSubscription(azure_subscription.subscription)
print(subscription.json)Docstringfrom cloudiq import CloudIQ
help(CloudIQ)API DocumentationCrayon API Documentation:https://apidocs.crayon.com/Swagger UI (includes all valid schemas):https://api.crayon.com/docs/index.htmlSchema currently implemented in CloudIQ classCustomerTenantDetailedCustomerTenantAgreementSubscriptionDetailedMethods currently implemented in CloudIQ classgetpingmegetTokenvalidateTokengetOrganizationsgetOrganizationgetOrganizationSalesContactgetAgreementProductsgetActivityLogsgetOrganizationHasAccessgetAddressesgetAddressgetSupportedBillingCyclesgetAgreementsgetAgreementReportsgetCustomerTenantsgetCustomerTenantgetCustomerTenantDetailsgetCustomerTenantAzurePlangetCustomerTenantAgreementsgetBillingCyclesgetProductVariantBillingCyclesgetBillingCyclesNameDictionarygetBillingStatementsgetGroupedBillingStatementsgetBillingStatementExcelgetBillingStatementCSVgetBillingStatementJSONgetBlogItemsgetClientsgetClientgetConsumersgetConsumergetCrayonAccountsgetCrayonAccountgetGroupingsgetGroupinggetInvoiceProfilesgetInvoiceProfilegetProductContainersgetProductContainergetProductContainerRowIssuesgetProductContainerShoppingCartgetProgramsgetProgramgetPublishersgetPublishergetRegionsgetRegionByCodegetUsersgetUsergetUsernamegetUsageCostdeletepatchpostputcreateClientdeleteClientcreateTenantcreateSubscriptioncreateTenantAgreement