- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 05-27-2020 01:35 AM
Add new cloud provider in Terraform Connector (AWS)
Step 1: Terraform AWS authentication
Step 2: Configure an AWS Datacenter Resource Block
Terraform simplifies orchestration of cloud deployments, helping operators build small- to large-scale multi-cloud infrastructures. Instead of creating specific CloudFormation templates for AWS, ARM templates for Azure, and Cloud Deployment Manager for GCP, Terraform lets you deploy across multiple providers using 'template’ files. The ServiceNow Cloud Management application (with the Terraform Connector from the ServiceNow Store) provides out of the box support for providers such as VMware, IBM and MS Azure clouds.
This article takes you through the procedures or steps needed to add a new cloud provider (AWS, in this example) to the Terraform Connector Store app. The main steps are:
- Map Credentials between Cloud Management and Terraform
- Add a Terraform orchestration interface on a resource block
After you have mapped the credentials and configured the resource block you can proceed to: - Create a Terraform config provider and run Discovery (OpenSource or Enterprise)
- Create catalog items based on Terraform templates
Step 1: Terraform AWS authentication:
The ServiceNow Cloud Management application supports credentials where we use access_key and secret_key as variable defined in template. The values of `keys’ is mapped from Discovery credentials.
You can use the (Infrastructure as Code) IaC Provider Settings user interface to perform credential and service account mappings for DataCenter credentials used by the Terraform provider to provision datacenter resources and Cloud Management for discovery. Mapping credential and service account fields between Cloud Management and Terraform using the IaC Provider Settings, enables you to store and manage credentials in an external credential repository rather than directly in a ServiceNow credentials record. See product documentation for detailed steps.
- This mapping is used to map values of Discovery credential’s keys to variables defined in terraform template.
- For above example, terraform commands will be:
- terraform apply -var secretkey = ‘1234XXXX…’ -var accesskey = ‘ABCXXXXX…’
- terraform destroy -var secretkey = ‘1234XXXX…’ -var accesskey = ‘ABCXXXXX…’
- Add terraform provider in IaC Settings:
- Discovery credential mapping with provider authentication keys.
- Final output after mapping:
Step 2: Configure an AWS Datacenter Resource Block:
Add the Terraform Orchestration interface on a resource block, to execute cloud-based operations via terraform templates. The product documentation has detailed instructions on setting up an Azure Datacenter resource block. The procedure is mostly similar except that the response processor scripts in this article are specifically for AWS Create Stack and Delete Stack operations. Similarly, you will need to create custom response processors for different resource types, e.g. if you want to add support for GCP and deploy a GCP cloud db - then a response mapping must be done for the cloud db instance.
- Go to Cloud Admin Portal à Design à ResourceBlock à AWS Datacenter
- Add Terraform Orchestration Interface to AWS Datacenter
- Add step to CreateStack operation:
Form Parameter |
Value |
Operation Type |
Invoke Cloud API |
API Provider |
Terraform OpenSource |
API Interface |
Configuration Orchestration Interface |
API Method |
ExecuteCommand |
CAPI Version |
1.0 |
Condition |
|
- Step Parameter Mapping:
Parameter |
Value |
AdditionalParameters |
{"ServerType":"$(Script:sn_cmp_terraform.TerraformCommandUtils.getConfigProviderServerTypeByName[arg=${parameter.WorkloadConfigProvider}])"} |
ConfigMgmtProviderInfo |
$(capiResolver.NodeCredentialResolver#nodeCredentialId=$(ci.sn_cmp_wl_cfg_mgmt_provider[name=${parameter.WorkloadConfigProvider}].credential)) |
ConfigurationParameters |
${parameter.ConfigurationParameters} |
NodeAddress |
$(ci.cmdb_ci_workload_config_provider[name=${parameter.WorkloadConfigProvider}].url) |
ProviderParameters |
${parameter.ProviderParameters} |
Script |
${CloudScript.scripts.TerraformDeploy} |
TemplateParameters |
${parameter.TemplateParameters} |
- Create response processor: AWS_TF_Provision_Response_Processor
Script:
function processResponse(response, cloudServiceAccountId, ldc,
correlationId, step, requestorContext, stackId) {
var responseObject = global.JSON.parse(response);
var tfState = global.JSON.parse(responseObject.terraform.state);
var processor = new sn_cmp_terraform.TerraformResponseProcessor();
var processedResponses = processor.processResponse(tfState, cloudServiceAccountId, ldc,
correlationId, step, requestorContext, stackId);
return global.JSON.stringify(processedResponses);
}
- Add response processor to step: AWS_TF_Provision_Response_Processor
- Final mapping:
- Add step to DeleteStack operation:
Form Parameter |
Value |
Operation Type |
Invoke Cloud API |
API Provider |
Terraform OpenSource |
API Interface |
Configuration Orchestration Interface |
API Method |
ExecuteCommand |
CAPI Version |
1.0 |
Condition |
|
- Step Parameter Mapping:
Parameter |
Value |
AdditionalParameters |
{"ServerType":"$(Script:sn_cmp_terraform.TerraformCommandUtils.getConfigProviderServerTypeByName[arg=${parameter.WorkloadConfigProvider}])"} |
ConfigMgmtProviderInfo |
$(capiResolver.NodeCredentialResolver#nodeCredentialId=$(ci.sn_cmp_wl_cfg_mgmt_provider[name=${parameter.WorkloadConfigProvider}].credential)) |
ConfigurationParameters |
${parameter.ConfigurationParameters} |
NodeAddress |
$(ci.cmdb_ci_workload_config_provider[name=${parameter.WorkloadConfigProvider}].url) |
ProviderParameters |
${parameter.ProviderParameters} |
Script |
${CloudScript.scripts.DestroyTerraform} |
TemplateParameters |
${parameter.TemplateParameters} |
- Create response processor: AWS_TF_Delete_Stack
- Script:
function processResponse(response, cloudServiceAccountId, ldc, correlationId,step, requestorContext, stackId) {
var responseObject = global.JSON.parse(response);
var tfResponse = responseObject.terraform;
var tfStateAfter = global.JSON.parse(tfResponse['state.after']);
var tfStateBefore = global.JSON.parse(tfResponse['state.before']);
var processor = new sn_cmp_terraform.DeprovisionTerraformResponseProcessor();
//there is no support for before state currently, hence its handled internally
var retiredStackItems = processor.updateStackItemTermination(stackId, tfStateBefore, tfStateAfter);
if(retiredStackItems)
gs.info('Retired CI\'s of stack items');
else
gs.warn('Havent retired CI\'s of stack items');
return global.JSON.stringify([{}]);
}
- Final Mapping:
Next Steps:
Create a Terraform config provider and run Discovery
Create catalog items based on Terraform templates
Reference material:
Resource Blocks
Configure a Response Processor
Execute response processor for workflow
Create a CI class for virtual cloud resource
Virtual server response processor example (AWS VM CIs)
- 3,561 Views
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Very cool. Thanks. I also created a detailed document on integrating Terraform with SN to provision resources on IBM Cloud
Please like or mark helpful if it helps
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Thankyou for putting this detailed example together. I have a VM and VPC provisioning in the AWS instance, however the response processing is failing with error
"Error :SyntaxError: Expected end of stream at char 4 (<refname>; line 7) com.snc.cloud.mgmt.modules.svccatalog.exception.SvcCatalogException: Javascript error when interpreting the evaluated response for response processor :Create_AWSTF_Stack_Response_Processor".
I have created the response processor on the AWS Data Centre resource block, but do I need to create a response processor for the automatically generated Terraform Resource block?
The error refers to a response processor which I cannot find in the system "Create_AWSTF_Stack_Response_Processor". Do you know where this can be found?
Thanks,
R