Author: Nishant Banga

Problem Statements:

RAML MIGRATION: We have a RAML created in Anypoint Design Center and an associated mule API deployed in cloudhub with Auto-discovery implemented. Now, whenever the developer makes changes to RAML in the design center, we have to update the latest version of RAML in the API manager and then automatically publish it to the exchange. We have to automate this task using jenkins pipeline and trigger this using SCM polling.

API PROMOTION: Automate the process of “Promoting an API instance to another Environment on API Manager” with policies. 

Requisites: Anypoint CLI, Batch Script, Jenkins, Git

Steps for RAML migration:

  1. Write a batch script which will be executed by jenkins pipeline. It will have the needed parameters and Anypoint CLI commands.
@echo off
set user=%1
set pwd=%2
set sourceEnv=%3
set asset=%4
echo %user% %pwd% %sourceEnv% %asset%
echo app started
for /f %%i in ('jsonextractor.bat exchange.json version') do set Version=%%i
echo version is %Version%
for /f %%i in ('jsonextractor.bat exchange.json apiversion') do set apiVersion=%%i
echo version is %apiVersion%
for /f %%i in ('anypoint-cli --username=%user% --password=%pwd% --environment=%sourceEnv% api-mgr api list -f "Instance ID" --assetId %asset% -o text') do set apiInstance=%%i
echo api instance is %apiInstance%
CALL anypoint-cli --username=%user% --password=%pwd% --environment=%sourceEnv% api-mgr api change-specification %apiInstance% %Version%
CALL anypoint-cli --username=%user% --password=%pwd%  designcenter project publish %asset% --apiVersion %apiVersion%  

This bat file will read the exchange.json file, which we have to pass with our mule app, and will fetch the api version and asset version. It will also fetch the api instance id when we pass the asset name. 

This batch script will also require json extractor bat file, which is following:

@if (@CodeSection == @Batch) @then
@echo off & setlocal
cscript /nologo /e:JScript "%~f0" %*
goto :EOF
@end // end batch / begin JScript hybrid chimera
var htmlfile = WSH.CreateObject('htmlfile');
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');
var JSON = htmlfile.parentWindow.JSON;
//needs file existence checks
var jsloc=WScript.Arguments.Item(0);
var jsonPath=WScript.Arguments.Item(1);
FSOObj = new ActiveXObject("Scripting.FileSystemObject");
var txtFile=FSOObj.OpenTextFile(jsloc,1);
var json=txtFile.ReadAll();
try {
	var jParsed=JSON.parse(json);
}catch(err) {
   WScript.Echo("Failed to parse the json content");
   htmlfile.close();
   txtFile.close();
   WScript.Exit(1);
   //WScript.Echo(err.message);
}
WScript.Echo(eval("JSON.stringify(jParsed."+jsonPath+")"));
htmlfile.close();
txtFile.close();
  1. Create a jenkins file in the mule app. Script is as follows:
pipeline {
  agent any
  stages {
    stage('build') { 
    	      environment {
        ANYPOINT_CREDENTIALS = credentials('wp.anypoint')
      }
       steps {
	    echo getChangedFilesList()
		script{
			if(getChangedFilesList() == 'true'){
				echo "${ANYPOINT_CREDENTIALS_USR}"  
				echo "${ANYPOINT_CREDENTIALS_PSW}"
				bat 'C:/Users/NishantBanga/Desktop/batchscripts/api-demo.bat %ANYPOINT_CREDENTIALS_USR% %ANYPOINT_CREDENTIALS_PSW% <environment> <demo-project-jen>'
			}
		}
	   } 
    }
  }
}
String getChangedFilesList() {
	print "entering function"
    changedFiles = ""
    for (changeLogSet in currentBuild.changeSets) { 
        for (entry in changeLogSet.getItems()) { // for each commit in the detected changes
            for (file in entry.getAffectedFiles()) {
                changedFiles+= (file.getPath()+ " ") // add changed file to list
		    }
        }
    }
	print "entering function"
	if(changedFiles.contains("exchange")){ return "true" }
	else { return "false" }
}

The function “getChangedFileList” will tell whether there is change in version or not , i.e. it will check whether the exchange.json file is changed when pushed in bitbucket or not. If it is changed, that means, the version has been changed.

  1. Create Jenkins pipeline

    Following things should be taken care of:
  • Creation of anypoint credentials.
  • Creation of bitbucket credentials.
  • Checking in the “ Poll SCM ” feature (setting expression as * * * * *) so that with every change in bitbucket, it will check whether it has to perform version update or not. Also select the branch.
Console Output
Started by an SCM change
Obtained jenkinsfile from git https://nishantbanga@bitbucket.org/nishantbanga/mule-proj-jenkins.git
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in C:\Program Files (x86)\Jenkins\workspace\mule-jen-pipe
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Declarative: Checkout SCM)
[Pipeline] checkout
using credential 443b704b-d1f1-4889-add4-5aa19384673e
 > git.exe rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git.exe config remote.origin.url https://nishantbanga@bitbucket.org/nishantbanga/mule-proj-jenkins.git # timeout=10
Fetching upstream changes from https://nishantbanga@bitbucket.org/nishantbanga/mule-proj-jenkins.git
 > git.exe --version # timeout=10
using GIT_ASKPASS to set credentials 
 > git.exe fetch --tags --force --progress -- https://nishantbanga@bitbucket.org/nishantbanga/mule-proj-jenkins.git +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git.exe rev-parse "refs/remotes/origin/master^{commit}" # timeout=10
 > git.exe rev-parse "refs/remotes/origin/origin/master^{commit}" # timeout=10
Checking out Revision 5db24460fa193766b6573165e5f86e55816bcc72 (refs/remotes/origin/master)
 > git.exe config core.sparsecheckout # timeout=10
 > git.exe checkout -f 5db24460fa193766b6573165e5f86e55816bcc72 # timeout=10
Commit message: "try38"
 > git.exe rev-list --no-walk 20624060865387a823d7b8b551d2abd587dd56c0 # timeout=10
Masking supported pattern matches of %ANYPOINT_CREDENTIALS% or %ANYPOINT_CREDENTIALS_USR% or %ANYPOINT_CREDENTIALS_PSW%
C:\Program Files (x86)\Jenkins\workspace\mule-jen-pipe>C:/Users/NishantBanga/Desktop/batchscripts/api-demo.bat **** **** Sandbox demo-project-jen 
**** **** Sandbox demo-project-jen
app started
version is "1.0.3"
api instance is 16232947
API instance "16232947" asset version changed to "1.0.3"

Finished: SUCCESS

Steps for API Promotion:

  1. Write a batch script which can be executed by jenkins pipeline or on command line (as per the use). It will have the needed parameters and Anypoint CLI commands.
@echo off
set user=%1
set pwd=%2
set sourceEnv=%3
set targetEnv=%4
for /f %%i in ('anypoint-cli --username=%user% --password=%pwd% --environment=%sourceEnv% api-mgr api list -f "Instance ID" --assetId %5 -o text') do set apiInstance=%%i
for /f "tokens=1*" %%i in ('anypoint-cli --username=%user% --password=%pwd% --environment=%sourceEnv% account environment describe %sourceEnv% -f ID -o json') do set sourceEnv%%i=%%j
echo api instance is %apiInstance%
echo source environment id is %sourceEnv"ID":%
set ID=%sourceEnv"ID":%
anypoint-cli --username=%user% --password=%pwd% --environment=%targetEnv% api-mgr api promote -p true %apiInstance% %ID%

This bat file will first fetch the api instance id using the asset name provided and then it will promote the api instance from source environment to target one.

You can run this batch script as:

api-promote.bat <username> <password> <source_environment> <target_environment> <assetName>

Another way to implement this is by using the jenkins pipeline, where we are supposed to call this bat file in the pipeline script (just like what we did in RAML migration).

Leave a Comment