MuleSoft Anypoint is an enterprise platform of an API event-driven structure that permits builders to create design and construct an API, and to call a couple of capabilities the place you’ll be able to share API templates and software property. It additionally has a central internet interface to handle, combine, safe, and monitor API efficiency.
Open API Specification
MuleSoft API improvement helps Open API specification.
The Open API Specification (OAS) is a regular follow of programming language and agonistic interface for HTTP APIs and offers service content material discovery capabilities with out precise entry to code ,documentation, community visitors inspection.
For this tutorial, we cannot be protecting the creation of the open API specification, however simply to notice: an Open API spec file must be created and outlined contained in the folder content material.
MuleSoft Versioning
MuleSoft makes use of 3 digits semantic versioning scheme which denotes the key, minor, and patch launch.
The Main model is for whenever you make incompatible or breaking API adjustments. The Minor model is for whenever you add performance in a backward-compatible method. The Patch model is whenever you make adjustments like documentation replace with out altering the spec.
The API model is totally different from the above versioning scheme and is specified within the OAS definition. An API incorporates every asset model signifying main/minor updates. Model v1
can comprise numerous asset variations; for instance, 1.0.0, 1.0.1, 1.0.2, and so on., and model v2
can comprise asset variations, example2.0.0, 2.0.1, 2.0.2, and so on.
Asset Lifecycle States
For the Asset Growth Lifecycle, we can be utilizing the MuleSoft lifecycle states beneath.
Growth State
That is an iterative strategy of design and improvement.
- Pattern asset in improvement state config file:
{
"assetId": "hello-worldsample-v1",
"status": "development",
"version": "1.0.1",
"classifier": "oas"
}
Steady State
The asset is prepared for consumption and in MuleSoft that is denoted by setting the standing to "published"
which truly means secure.
- Pattern asset within the secure state config file:
{
"assetId": "hello-worldsample-v1",
"status": "published",
"version": "1.0.1",
"classifier": "oas"
}
Deprecated State
Deprecated flags the API and can be utilized to earmark the API for deletion. We can’t be utilizing this state on this tutorial.
- Asset Id: Id of an asset (API) revealed to the Trade (API Catalog)
- Asset model: Model of the asset (API) revealed to the Trade (API catalog)
- Classifier: The kind of API specification; on this case, it’s OAS (Open API specification)
Automated launch tags allotted in line with asset state:
ASSET STATE | FOLDER | CUSTOM RELEASE VERSIONING LOGIC | SAMPLE RELEASE TAG |
---|---|---|---|
Growth |
world config file |
develop-mulesoftAPIVersion.timestamp |
develop-1.0.1.166720192 |
Steady |
world config file |
stable-mulesoftAPIVersion.timestamp |
stable-1.0.1.166720192 |
Customized Launch Tagging Scheme
On this tutorial, we’ve devised a customized tagging scheme that we are able to make the most of throughout our launch section to tag the codebase with this practice tag. This helps us to trace the actual MuleSoft launch improvement all the way in which to the deployment of an API to a selected setting because it will get promoted to the manufacturing setting.
Ideally, you do not have to observe the identical logic for tagging. You possibly can devise your individual customized primarily based on the Asset and environment-related deployments in MuleSoft.
Since we can be configuring a customized tag primarily based on a selected setting deployment, the MuleSoft model can be used contained in the tag indicated beneath with mulesoftAssetVersion
with the offered pattern as “1.0.1
“.
- Automated launch tags in line with setting deployment:
ENVIRONMENT | FOLDER | CUSTOM RELEASE VERSIONING LOGIC | SAMPLE RELEASE TAG |
---|---|---|---|
Growth |
dev |
dev-deploy-mulesoftAssetVersion.timestamp |
dev-deploy-1.0.1.166720192 |
High quality Assurance |
qa |
qa-deploy-mulesoftAssetVersion.timestamp |
qa-deploy-1.0.1.166720192 |
Manufacturing |
prod |
prod-deploy-mulesoftAssetVersion.timestamp |
prod-deploy-1.0.1.166720192 |
For this tutorial, we’ve arrange the beneath automated customized launch versioning and tagging scheme.
The code improvement relies on Trunk primarily based improvement with a single stream of improvement. The sequence of adjustments as indicated within the beneath diagram begins when a developer cuts a function department for his or her improvement functions. They’ve the pliability to amend the adjustments within the world config (sits exterior the setting folders) or the OAS file for improvement and publishing for the actual asset to the MuleSoft Trade. On the finish of the event, they will set the Asset state to revealed or improvement and create a pull request to merge onto the grasp department.
As soon as the asset is obtainable on an trade, the developer can configure the environment-related asset config recordsdata or API coverage recordsdata that are environment-specific and allow the developer to eat any of the revealed asset variations within the environment-specific asset config for API deployment functions solely. For instance, the Dev setting can deploy 1.0.3 of an asset, whereas the QA setting can use 1.0.2 and the prod can deploy 1.0.1. API insurance policies may be utilized in a similar way whereas Dev and QA use a special set of API insurance policies and Prod can use a special set of API insurance policies.
The Azure CI/CD pipeline has been arrange in a approach that after the pull the request for merge to grasp has been permitted, it mechanically senses the adjustments for the states within the world asset config file and environment-specific file adjustments and triggers the deployment of an Asset or MuleSoft API primarily based on the adjustments utilized to sure recordsdata then creates a tag primarily based on a set of adjustments that the developer has initiated.
MuleSoft Customized Launch Model Tagging Scheme
Because the Azure CI/CD pipeline is exterior the scope of this tutorial, we cannot be protecting this on this tutorial.
Create Folder Construction
To create a folder construction in line with your setting necessities, we’ve created the beneath folder construction.
Mother or father Folder Identify
You possibly can set this to the identify of your API and main model; for instance, helloWorldSample-V1
(notice that V1 on this occasion signifies the key model of the API).
config.json
(sitting exterior the setting folders) – Used for the event and publishing of the actual asset to the MuleSoft tradehello-oas.yaml
(sitting exterior the setting folders) – API OAS file for improvement and publishing for the actual asset to MuleSoft runtimeREADME.md
– Learn me file for description, and tutorial notes in regards to the repository content materialdev env
config.json
– Used for an API deployment on MuleSoft with the actual related asset identify and model specified inside this filecoverage.json
– Used to outline customized API coverage payload that can utilized to the API on the settingtls-context.json
– Used to outline environment-level customized TLS context for binding to inbound / outbound API requests.
qa env
– Identical folder construction asdev env
; Notice: the precise content material of particular person JSON recordsdata will fluctuate in line with environment-specific necessities.prod env
– Identical folder construction asdev env
; Notice: the precise content material of particular person JSON recordsdata will fluctuate in line with environment-specific necessities.
Content material of Recordsdata
- Config.json (sitting exterior the setting folders):
{
"assetId": "helloWorldSample-v1",
"status": "published", #change this to "development" in case you are growing the asset.
"version": "1.0.1",
"classifier": "oas"
}
- hello-oas.yaml (sitting exterior the setting folders):
You possibly can create the pattern hello-oas.yaml file or an instance file by referring to this hyperlink.
{
"assetId": "helloWorldSample-v1",
"version": "1.0.1",
"classifier": "oas"
}
coverage.json
(pattern coverage file):
{
"policy": [
{
"configurationData": {
"clusterizable": true,
"exposeHeaders": true,
"rateLimits": [
{
"timePeriodInMilliseconds": 5000,
"maximumRequests": 1000
}
]
},
"order": 1,
"pointcutData": null,
"assetId": "rate-limiting",
"assetVersion": "1.0.0",
"groupId": "$(groupId)"
},
{
"configurationData": {
"credentialsOriginHasHttpBasicAuthenticationHeader": "customExpression",
"clientIdExpression": "#[attributes.headers['client_id']]",
"clientSecretExpression": "#[attributes.headers['client_secret']]"
},
"order": 2,
"disabled": false,
"pointcutData": null,
"groupId": "$(groupId)",
"assetId": "client-id-enforcement",
"assetVersion": "1.3.2"
}
]
}
tls-context.json
(pattern JSON file) – Notice: “masked $(variables)
” to be handed by way of pipeline; you’ll be able to change this to some other legitimate variable or worth.
{
"tlsContext_InputParameters": {
"technology": "mule4",
"endpoint": {
"type": "rest",
"deploymentType": "CH",
"proxyUri": "https://0.0.0.0:8092/api",
"isCloudHub": true,
"referencesUserDomain": false,
"responseTimeout": null,
"muleVersion4OrAbove": true,
"tlsContexts": {
"inbound": {
"tlsContextId": "$(inboundtlsContextId)",
"name": "$(inboundTlsname)",
"secretGroupId": "$(inboundsecretGroupId)"
},
"outbound": {
"tlsContextId": "$(outboundtlsContextId)",
"name": "$(outboundTlsname)",
"secretGroupId": "$(outboundsecretGroupId)"
}
}
}
}
}
Seize Config Adjustments
For this, we used Python code to seize the record of adjustments after which generate a JSON file primarily based on the record of adjustments.
Import Libraries
import subprocess;
from subprocess import Popen, PIPE;
import sys;
import getopt;
import os;
Create JSON Capabilities
import json;
def get_json_key_value(filename, key):
with open(filename, 'r') as config_file:
config_data = json.load(config_file)
return (config_data[''+key+''])
def create_json_file(json_data, json_file):
jsonString = json.dumps(json_data)
jsonFile = open(json_file, "w")
jsonFile.write(jsonString)
jsonFile.shut()
Create cmd Capabilities
from subprocess import *;
from os import chdir
def run_cmd(git_command, use_shell=True):
"""Run's the given git command, throws exception on failure"""
return check_output(git_command, shell=use_shell)
def create_folder(path):
'''Verify if listing exists, if not, create it'''
import os
# It's best to change 'take a look at' to your most popular folder.
CHECK_FOLDER = os.path.isdir(path)
# If folder does not exist, then create it.
if not CHECK_FOLDER:
os.makedirs(path)
print("created folder : ", path)
else:
print(path, "folder already exists.")
Create an Array
Create an array for the modified recordsdata and a tags dictionary inside an array.
modified_files = []
tag_dict = []
counter = 0
# Output folder path
outputFolder = ".output"
Create Timestamp Operate
import calendar;
import time;
def get_timestamp():
return calendar.timegm(time.gmtime())
Get and append the array of modified recordsdata utilizing the Git command to collect the record of file adjustments.
modified_file_list = (subprocess.Popen(['git show --pretty"=format:" --name-only'], shell=True,stdout=subprocess.PIPE).talk()[0].decode('utf-8').strip())
modified_files.append(modified_file_list.cut up())
# Create dictionary for modified recordsdata and assign tags
for modified_file in modified_files:
for file in modified_file:
counter += 1
## For Asset Standing set to improvement
if (((file == "config.json") or (file.endswith('.yaml'))) and ((get_json_key_value("config.json", "status")) == 'improvement')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'develop-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())})
## For Asset Standing set to revealed
if (((file == "config.json") or (file.endswith('.yaml'))) and ((get_json_key_value("config.json", "status")) == 'revealed')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'stable-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())})
## For Growth setting deployment
if (file.startswith('dev/')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'dev-deploy-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())})
## For QA setting deployment
if (file.startswith('qa/')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'qa-deploy-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())})
## For Prod setting deployment
if (file.startswith('prod/')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'prod-deploy-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())}
Create Output Folder
# Create .output folder if it doesn't exisit
create_folder(outputFolder)
Create JSON Tags File
# Create Tags json file
create_json_file(tag_dict, outputFolder+"/git_tags.json")
If all is configured correctly, the script will generate the beneath JSON tags file.
[
{
"order": 1,
"fileChanged": "config.json",
"tag": "stable-1.0.0.1663027933"
},
{
"order": 2,
"fileChanged": "dev/config.json",
"tag": "dev-deploy-1.0.0.1663027933"
},
{
"order": 3,
"fileChanged": "qa/config.json",
"tag": "qa-deploy-1.0.0.1663027933"
},
{
"order": 4,
"fileChanged": "prod/config.json",
"tag": "prod-deploy-1.0.0.1663027933"
}
]
We then seize the suitable Tags utilizing the bash script after which assign it variables utilizing jq.
The variables can then be used within the pipeline to mechanically set off additional deployment duties.
# Use jq to learn the Json Tags and assign it to the variable
API_STATUS=`${JQ_TOOL_PATH}jq -r '.[]| choose(.tag | startswith("develop-") or startswith("stable-")) |.tag' ${API_CONFIG_FILE}`
DEV_DEPLOY_STATUS=`${JQ_TOOL_PATH}jq -r '.[]| choose(.tag | startswith("dev-deploy-"))|.tag' ${TAG_FILE}`
QA_DEPLOY_STATUS=`${JQ_TOOL_PATH}jq -r '.[]| choose(.tag | startswith("qa-deploy-"))|.tag' ${TAG_FILE}`
PROD_DEPLOY_STATUS=`${JQ_TOOL_PATH}jq -r '.[]| choose(.tag | startswith("prod-deploy-"))|.tag' ${TAG_FILE}`
# Assign Azure Variables
echo "##vso[task.setvariable variable=TAG_API_STATUS;]${API_STATUS}"
echo "##vso[task.setvariable variable=TAG_dev_DEPLOY_STATUS;]${DEV_DEPLOY_STATUS}"
echo "##vso[task.setvariable variable=TAG_qa_DEPLOY_STATUS;]${QA_DEPLOY_STATUS}"
echo "##vso[task.setvariable variable=TAG_prod_DEPLOY_STATUS;]${PROD_DEPLOY_STATUS}"
We used the Pipeline process beneath in Azure DevOps to create a tag on the finish of the deployment duties.
Assign the Tag with the suitable variable on the finish of the deployment, as within the instance beneath.
Conclusion
As soon as the pipeline has run efficiently you’ll be able to take a look at this by altering any of the environment-level recordsdata and merging them to the grasp by way of pull request. The remainder of the steps are principally automated. Then you’ll be able to browse to the code repository tags part after which you need to see the beneath tag for example.