Contact Us 1-800-596-4880

Automating Flex Gateway with a Jenkins Pipeline using Anypoint CLI

You can use a Jenkins Pipeline to automate the workflow for Flex Gateway in Connected Mode. With a Jenkins Pipeline, you can register and run a Flex Gateway and use features of the Anypoint CLI, such as creating and deploying API instances.

To add additional features from the API Manager CLI, see CLI for API Manager.

This tutorial has different steps with different code blocks. As you work through the steps, add the code blocks to the same Jenkinsfile. If you are unfamiliar with the syntax used in a Jenkins Pipeline, see the Jenkins Pipeline documentation.

Automating your Flex Gateway with Anypoint CLI shares many similarities with Automating your Flex Gateway with the API Manager API. To automate your Flex Gateway using API Manger API requests, see Automating Flex Gateway with a Jenkins Pipeline using the API Manager API.

Before You Begin

Before you can deploy a Jenkins Pipeline, complete the following tasks:

  1. Download Flex Gateway.

  2. Configure a Connected App:

    1. Use the App acts on its behalf (client credentials) type and include the following scopes:

      • API Manager: Manage APIs Configuration, Manage Policies, View Policies, and Deploy API Proxies

      • Runtime Manager: Read Servers and Manage Servers

      • Exchange: Exchange Viewer

      • General: View Organization

    2. Save the Id and Secret of the Connected app you configure.

  3. Collect the group ID, asset ID, and asset version (GAV) of the Exchange asset (API) you want to create or apply.

    To collect your GAV from Exchange:

    1. Go to Exchange.

    2. Find the asset to add or apply.

    3. Collect the group ID and asset ID from the URL.

      For example, the IDs collected from the API Manager API Exchange URL, https://anypoint.mulesoft.com/exchange/portals/anypoint-platform/f1e97bc6-315a-4490-82a7-23abe036327a.anypoint-platform/api-manager-api/minor/1.0/pages/home/, are:

      • Group ID: f1e97bc6-315a-4490-82a7-23abe036327

      • Asset ID: api-manager-api

    4. Collect the asset version from Latest Stable.

      For example, the version collected from the API Gateway HTTP basic authentication policy template is 1.3.2.

  4. Collect the following information from your Anypoint Platform instance:

Initial Configuration

Before you can create and deploy an API instance to your Flex Gateway, you must complete the following steps:

After you implement these Pipeline stages, you can customize your Pipeline by making API Manager CLI requests to manage APIs.

Define Useful Functions

To begin, define these useful functions before the pipeline block in your Jenkinsfile:

def parseYamlFile(String file) {
    object = readYaml file: file
    return object
}

def getAPIInstanceID(String file) {
    return readFile(file: file).split(' ').last().replace('\n', '').trim()
}

Define Useful Parameters

Since the commands in the Jenkins Pipeline reuse some parameters, it is helpful to define them at the beginning of your Jenkinsfile.

Using the included parameter definitions as a template, you can also define any parameters that additional APIs or policies need.

To define the parameters:

  1. Collect the following information:

    • <your-org-id>: Organization ID for the organization where you want to run Flex Gateway

    • <your-env-id>: Environment ID for the organization where you want to run Flex Gateway

    • <gateway-version>: Version of Flex Gateway you are using, for example 1.4.0

    • <connected-app-client-id>: Id of your connected app

    • <connected-app-client-secret>: Secret of your connected app

    • API GAV:

      • <asset-group-id>: Group ID, obtained from Exchange

      • <asset-id-from-exchange>: Asset ID, obtained from Exchange, of the API you want to create

      • <asset-version>: Asset version, obtained from Exchange, of the API you want to create

    • <gateway-name>: Name of your Flex Gateway

  2. After replacing the sample content, add the parameter definitions to your Jenkinsfile to validate whether all parameters are present. Define the parameters in the pipeline block before the stages block:

    parameters {
        string(name: 'ENV_ID', defaultValue: '<your-env-id>', description: 'Your environment id')
        string(name: 'ORG_ID', defaultValue: '<your-org-id>', description: 'Your organization id')
        string(name: 'FLEX_VERSION', defaultValue: '<gateway-version>', description: 'Flex version to run')
        string(name: 'CONNECTED_APP_CLIENT_ID', defaultValue: '<connected-app-client-id>', description: 'Your connected app client id')
        string(name: 'CONNECTED_APP_CLIENT_SECRET', defaultValue: '<connected-app-client-secret', description: 'Your connected app client secret')
        string(name: 'EXCHANGE_ASSET_ID', defaultValue: '<asset-id-from-exchange>', description: 'The id of the http api exchange asset')
        string(name: 'EXCHANGE_ASSET_VERSION', defaultValue: '<asset-version>', description: 'The version of the http api exchange asset')
        string(name: 'GATEWAY_NAME', defaultValue: '<gateway-name>', description: 'Unique gateway name')
    }
  3. Add the check parameters stage to the stages block in your Jenkinsfile:

    stage('Check parameters') {
        steps {
            script {
                if (!params.ENV_ID || !params.ORG_ID || !params.GATEWAY_NAME || !params.FLEX_VERSION || !params.CONNECTED_APP_CLIENT_ID || !params.CONNECTED_APP_CLIENT_SECRET || !params.EXCHANGE_ASSET_ID || !params.EXCHANGE_ASSET_VERSION)  {
                    error("Not all parameters where specified")
                }
            }
        }
    }

    If this stage fails, specify the missing parameters and rerun the Pipeline.

Install Anypoint CLI 4.x

To install Anypoint CLI 4.x to your Docker container, add the install Anypoint CLI 4.x stage to the stages block in your Jenkinsfile:

stage('Install anypoint-cli-v4') {
    steps {
        script {
            sh """
                docker run --name container-anypoint-cli-v4 -d node:16 \
                sh -c " npm install -g anypoint-cli-v4 ; anypoint-cli-v4 plugins:install anypoint-cli-api-mgr-plugin; \
                while :; do sleep 1; done"
            """
            sh """
                docker exec container-anypoint-cli-v4 \
                sh -c "while ! anypoint-cli-v4 plugins 2> /dev/null | grep -q "anypoint-cli-api-mgr-plugin"; do :; done"
            """
        }
    }
}

Register and Run

Add the register and run stages to the stages block in your Jenkinsfile:

stage('Register flex gateway') {
   steps {
       script {
           sh """
               docker run --entrypoint flexctl \
                -v ${pwd()}:/registration -u 0 mulesoft/flex-gateway:${params.FLEX_VERSION} \
                register \
                --client-id=${params.CONNECTED_APP_CLIENT_ID} \
                --client-secret=${params.CONNECTED_APP_CLIENT_SECRET} \
                --environment=${params.ENV_ID} \
                --connected=true \
                --organization=${params.ORG_ID} \
                --output-directory=/registration \
                ${params.GATEWAY_NAME}
           """

           sh """
               grep "name: registration" registration.yaml
           """
       }
   }
}


stage('Run flex gateway') {
    steps {
        script {
            sh """
                docker run --name flex-gw -d \
                -v ${pwd()}:/usr/local/share/mulesoft/flex-gateway/conf.d \
                -p 8082:8082 \
                mulesoft/flex-gateway:${params.FLEX_VERSION}
            """
        }
    }
}

Create an API Instance

After installing Anypoint CLI 4.x, you can create an API instance and deploy it to your Flex Gateway.

You can repeat this step to add multiple API instances. For additional API configuration flags, see the api-mgr:api:manage command.

Add the create API instance stage to the stages block in your Jenkinsfile:

stage("Create API Instance") {
    steps {
        script {
            sh """
                docker exec container-anypoint-cli-v4 anypoint-cli-v4 api-mgr:api:manage ${params.EXCHANGE_ASSET_ID} ${params.EXCHANGE_ASSET_VERSION} \
                --client_id=${params.CONNECTED_APP_CLIENT_ID} --client_secret=${params.CONNECTED_APP_CLIENT_SECRET} \
                --isFlex --withProxy --deploymentType=hybrid --scheme=http --port=8082 \
                --uri=https://httpbin.org:443 --path=/httpbin > api-response
            """
        }
    }
}
For example, this stage creates an API instance that listens on port 8082 and /httpbin path and proxies to https://httpbin.org/443.

Apply a Basic Authentication Policy

After you create an API instance, you can apply policies to the API instance.

This stage applies the Basic Authentication: Simple Policy as an example, but you can apply any Connected Mode policy. To find additional policies, see Included Policies Directory.

To apply a policy:

  1. Collect the following information:

    • Policy GAV

      • <policy-group-id>: Policy group ID from Exchange, for example 68ef9520-24e9-4cf2-b2f5-620025690913`

      • <policy-asset-id>: Policy asset ID from Exchange, for example http-basic-authentication

      • <policy-asset-version>: Policy asset version from Exchange, for example 1.3.2

    • "configurationData": Policy configuration data

      The configuration data fields are dependent on the policy. The Basic Authentication: Simple policy uses parameters "username" and "password".

  2. After replacing the sample content, add the apply basic authentication policy stage to the stages block in your Jenkinsfile:

stage("Apply Basic Authentication Policy to API Instance") {
    steps {
        script {
            def apiInstanceId = getAPIInstanceID('api-response')
            sh """
                docker exec container-anypoint-cli-v4 anypoint-cli-v4 api-mgr:policy:apply ${apiInstanceId} 'http-basic-authentication' \
                --policyVersion='1.3.1' --groupId '68ef9520-24e9-4cf2-b2f5-620025690913' \
                --client_id=${params.CONNECTED_APP_CLIENT_ID} --client_secret=${params.CONNECTED_APP_CLIENT_SECRET} \
                -c '{"username": "user", "password": "test"}'
            """
        }
    }
}
For example, this stage uses the policy GAV and "configurationData" associated with the Basic Authentication: Simple Policy.

Deploy an API Instance

After you create an API instance, you can deploy the instance.

To deploy the new instance, add the deploy API stage to the stages block in your Jenkinsfile:

stage("Deploy API") {
    steps {
        script {
            sleep(time:15, unit:"SECONDS")
            def registration_file = parseYamlFile('registration.yaml')
            def apiInstanceId = getAPIInstanceID('api-response')

            sh """
                docker exec container-anypoint-cli-v4 anypoint-cli-v4 api-mgr:api:deploy ${apiInstanceId} \
                --client_id=${params.CONNECTED_APP_CLIENT_ID} --client_secret=${params.CONNECTED_APP_CLIENT_SECRET} \
                --target=${registration_file.spec.platformConnection.agentId[0]} --gatewayVersion=${params.FLEX_VERSION}
            """
        }
    }
}

Validate the API Instance is Deployed

After you deploy your API instance, validate whether the instance is deployed by adding the validate deployment stage to the stages block in your Jenkinsfile:

stage("Validate Deployment") {
    steps {
        script {
            sleep(time:10, unit:"SECONDS")

            def unauthorized_status_code = sh(script: "curl -s -w \"%{http_code}\" -o /dev/null http://localhost:8082/httpbin/headers -v", returnStdout: true).trim().toInteger()
            if (unauthorized_status_code != 401) {
                error("401 status code expected but the status code obtained is ${unauthorized_status_code}")
            }

            def authorized_status_code = sh(script: "curl -s -w \"%{http_code}\" -o /dev/null http://localhost:8082/httpbin/headers -v -u user:test", returnStdout: true).trim().toInteger()
            if (authorized_status_code != 200) {
                error("200 status code expected but the status code obtained is ${unauthorized_status_code}")
            }
        }
    }
}

Stop the Flex Gateway and Archive the Registration File

Use the following code blocks to archive the registration file and remove the Docker container running Flex Gateway. Add the post block in the pipeline block after the stages block:

post {
    success {
        script {
            // Archive the build output artifacts.
            archiveArtifacts artifacts: 'registration.yaml'
        }
    }
    always {
        script {
            sh(script: "docker rm -f container-anypoint-cli-v4 flex-gw")
        }
    }
}