Automating Flex Gateway with a Jenkins Pipeline using Anypoint CLI | MuleSoft Documentation
# 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:
     * **Organization ID** for the organization where you want to run Flex Gateway
For more information, see Find Your Organization ID.
     * **Environment ID** for the environment where you want to run Flex Gateway
For more information, see What API Manager Looks Like.


## Initial Configuration
Before you can create and deploy an API instance to your Flex Gateway, you must complete the following steps:
  1. Define Useful Functions.
  2. Define Useful Parameters.
  3. Install Anypoint CLI 4.x
  4. Register and Run.


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}
      """
    }
  }
}
```
### 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")
    }
  }
}
```

## See Also
  * Anypoint Platform CLI 4.x Overview
  * Registering and Running in Connected Mode with a Connected App.
  * Manage Flex Gateway Using the API Manager API