MuleSoft Anypoint is an enterprise platform of an API event-driven structure that enables builders to create design and construct an API, and to call a couple of capabilities the place you may share API templates and software property. It additionally has a central net 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 normal observe of programming language and agonistic interface for HTTP APIs and gives service content material discovery capabilities with out precise entry to code ,documentation, community site visitors inspection.
For this tutorial, we cannot be overlaying 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 while you make incompatible or breaking API modifications. The Minor model is for while you add performance in a backward-compatible method. The Patch model is while you make modifications 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 comprises every asset model signifying main/minor updates. Model v1
can comprise quite a few asset variations; for instance, 1.0.0, 1.0.1, 1.0.2, and so forth., and model v2
can comprise asset variations, example2.0.0, 2.0.1, 2.0.2, and so forth.
Asset Lifecycle States
For the Asset Growth Lifecycle, we shall be utilizing the MuleSoft lifecycle states beneath.
Growth State
That is an iterative technique 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 steady.
- Pattern asset within the steady 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 cannot be utilizing this state on this tutorial.
- Asset Id: Id of an asset (API) printed to the Alternate (API Catalog)
- Asset model: Model of the asset (API) printed to the Alternate (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 |
international config file |
develop-mulesoftAPIVersion.timestamp |
develop-1.0.1.166720192 |
Steady |
international config file |
stable-mulesoftAPIVersion.timestamp |
stable-1.0.1.166720192 |
Customized Launch Tagging Scheme
On this tutorial, we now have devised a customized tagging scheme that we will 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 best way to the deployment of an API to a selected surroundings because it will get promoted to the manufacturing surroundings.
Ideally, you do not have to observe the identical logic for tagging. You’ll be able to devise your personal customized primarily based on the Asset and environment-related deployments in MuleSoft.
Since we shall be configuring a customized tag primarily based on a selected surroundings deployment, the MuleSoft model shall be used contained in the tag indicated beneath with mulesoftAssetVersion
with the offered pattern as “1.0.1
“.
- Automated launch tags in line with surroundings 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 now have arrange the beneath automated customized launch versioning and tagging scheme.
The code improvement is predicated on Trunk primarily based improvement with a single stream of improvement. The sequence of modifications as indicated within the beneath diagram begins when a developer cuts a characteristic department for his or her improvement functions. They’ve the flexibleness to amend the modifications within the international config (sits outdoors the surroundings folders) or the OAS file for improvement and publishing for the actual asset to the MuleSoft Alternate. On the finish of the event, they will set the Asset state to printed or improvement and create a pull request to merge onto the grasp department.
As soon as the asset is accessible on an change, the developer can configure the environment-related asset config recordsdata or API coverage recordsdata that are environment-specific and allow the developer to devour any of the printed asset variations within the environment-specific asset config for API deployment functions solely. For instance, the Dev surroundings can deploy 1.0.3 of an asset, whereas the QA surroundings 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 unique set of API insurance policies and Prod can use a unique set of API insurance policies.
The Azure CI/CD pipeline has been arrange in a means that after the pull the request for merge to grasp has been authorized, it routinely senses the modifications for the states within the international asset config file and environment-specific file modifications and triggers the deployment of an Asset or MuleSoft API primarily based on the modifications utilized to sure recordsdata then creates a tag primarily based on a set of modifications that the developer has initiated.
MuleSoft Customized Launch Model Tagging Scheme
For the reason that Azure CI/CD pipeline is outdoors the scope of this tutorial, we cannot be overlaying this on this tutorial.
Create Folder Construction
To create a folder construction in line with your surroundings necessities, we now have created the beneath folder construction.
Mother or father Folder Identify
You’ll be able to set this to the title 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 outdoors the surroundings folders) – Used for the event and publishing of the actual asset to the MuleSoft changehello-oas.yaml
(sitting outdoors the surroundings 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 title and model specified inside this filecoverage.json
– Used to outline customized API coverage payload that can utilized to the API on the surroundingstls-context.json
– Used to outline environment-level customized TLS context for binding to inbound / outbound API requests.
qa env
– Similar folder construction asdev env
; Word: the precise content material of particular person JSON recordsdata will fluctuate in line with environment-specific necessities.prod env
– Similar folder construction asdev env
; Word: the precise content material of particular person JSON recordsdata will fluctuate in line with environment-specific necessities.
Content material of Recordsdata
- Config.json (sitting outdoors the surroundings folders):
{
"assetId": "helloWorldSample-v1",
"status": "published", #change this to "development" in case you are creating the asset.
"version": "1.0.1",
"classifier": "oas"
}
- hello-oas.yaml (sitting outdoors the surroundings folders):
You’ll be able to 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) – Word: “masked $(variables)
” to be handed by way of pipeline; you may 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 listing of modifications after which generate a JSON file primarily based on the listing of modifications.
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):
'''Test if listing exists, if not, create it'''
import os
# You must change 'take a look at' to your most well-liked folder.
CHECK_FOLDER = os.path.isdir(path)
# If folder would 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 listing of file modifications.
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 printed
if (((file == "config.json") or (file.endswith('.yaml'))) and ((get_json_key_value("config.json", "status")) == 'printed')):
tag_dict.append({'order': counter, 'fileChanged': file, 'tag': 'stable-'+(
get_json_key_value("config.json", "version"))+'.'+str(get_timestamp())})
## For Growth surroundings 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 surroundings 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 surroundings 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 routinely 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 may 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 may browse to the code repository tags part after which it is best to see the beneath tag for instance.