Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Deploy your API from a Jenkins Pipeline

July 30, 2019
Nicolas Massé
Related topics:
CI/CDDevOps
Related products:
Red Hat 3scale API Management

Share:

    In a previous article, 5 principles for deploying your API from a CI/CD pipeline, we discovered the main steps required to deploy your API from a CI/CD pipeline and this can prove to be a tremendous amount of work. Hopefully, the latest release of Red Hat Integration greatly improved this situation by adding new capabilities to the 3scale CLI. In 3scale toolbox: Deploy an API from the CLI, we discovered how the 3scale toolbox strives to automate the delivery of APIs. In this article, we will discuss how the 3scale toolbox can help you deploy your API from a Jenkins pipeline on Red Hat OpenShift/Kubernetes.

    Running the 3scale toolbox from Jenkins

    When calling a CLI from within a Jenkins Pipeline, at least three different strategies are possible:

    • You can create a custom Jenkins Slave image containing the CLI.
    • You can install the CLI on the fly during the pipeline run.
    • Or, you can spin up a Kubernetes Job or Pod calling the CLI in a container.

    The custom Jenkins Slave has the drawback of being yet another container image to build, manage, troubleshoot, secure, etc. It also means credentials need to be managed from within Jenkins which require a proprietary plugin to apply RBAC on them. Installing the CLI on-the-fly works well for static binaries, such as jq or the oc command, but not so well for a Ruby program. Also, credentials need to be managed from within Jenkins.

    The Kubernetes Job/Pod solution has the advantage of removing any dependency/preparatory work. It allows credentials management in OpenShift/Kubernetes (and thus subject to RBAC) and is future proof because it's the way the Tekton pipelines are working.

    To deploy your API from a Jenkins Pipeline, run the 3scale toolbox as Kubernetes Jobs.

    Running the 3scale toolbox from Jenkins

    To run the 3scale toolbox as Kubernetes Jobs from a Jenkins Pipeline, we need to write a small helper function:

    def runToolbox(args) {
      def kubernetesJob = [
        "apiVersion": "batch/v1",
        "kind": "Job",
        "metadata": [
          "name": "toolbox"
        ],
        "spec": [
          "backoffLimit": 0,
          "activeDeadlineSeconds": 300,
          "template": [
            "spec": [
              "restartPolicy": "Never",
              "containers": [
                [
                  "name": "job",
                  "image": "quay.io/redhat/3scale-toolbox:master",
                  "imagePullPolicy": "Always",
                  "args": [ "3scale", "version" ],
                  "env": [
                    [ "name": "HOME", "value": "/config" ]
                  ],
                  "volumeMounts": [
                    [ "mountPath": "/config", "name": "toolbox-config" ],
                    [ "mountPath": "/artifacts", "name": "artifacts" ]
                  ]
                ]
              ],
              "volumes": [
                [ "name": "toolbox-config", "secret": [ "secretName": "3scale-toolbox" ] ],
                [ "name": "artifacts", "configMap": [ "name": "openapi" ] ]
              ]
            ]
          ]
        ]
      ]
    
      kubernetesJob.spec.template.spec.containers[0].args = args
    
      sh "rm -f -- job.yaml"
      writeYaml file: "job.yaml", data: kubernetesJob
      sh """
      oc delete job toolbox --ignore-not-found
      sleep 2
      oc create -f job.yaml
      sleep 20 # Adjust the sleep duration to your server velocity
      """
    
      def logs = sh(script: "oc logs -f job/toolbox", returnStdout: true)
      echo logs
      return logs
    }

    This function starts by defining a Kubernetes Job template that you can customize to match your environments. In particular, you can adjust:

    • backoffLimit: Keep it at 0 during pipeline development and bump it to 2 once your pipeline is ready to use. The backoff limit determines how many attempts will be performed in case of error.
    • activeDeadlineSeconds: 300 seconds should be plenty to complete a toolbox execution, but you might need to set it to a higher value if your servers are slow, very loaded or if your API contains a lot of operations.
    • image: You can use the community image on quay.io or the official Red Hat image if you are a Red Hat customer (3scale-amp26/toolbox).

    The Job template is then patched with the supplied command-line arguments. The resulting job is stored as a YAML file and deployed in OpenShift using the oc command. Just after the oc command, the pipeline waits a couple of seconds to allow the Kubernetes Job to create the container and let it transition from the "ContainerCreated" to "Running" state. You can adjust this wait time according to your server velocity or even better, replace it with a polling loop. Finally, once the container transitioned to the "Running" state, the function fetches its logs and returns them to the caller.

    As you can see, the Job receives two mount points:

    • A Kubernetes Secret for the 3scale toolbox configuration file that contains the remote list.
    • A Kubernetes ConfigMap for the artefacts to provision (OpenAPI Specification file, Application Plan file, etc.).

    The ConfigMap will be created by the Jenkins Pipeline. The secret is provisioned outside of the pipeline and subject to RBAC.

    Provision the 3scale-toolbox secret in the same OpenShift project as your Jenkins Master:

    3scale remote add 3scale-instance "https://[email protected]/"
    oc create secret generic 3scale-toolbox --from-file="$HOME/.3scalerc.yaml"
    

    Note: In the rest of this article, we are showcasing a 3scale hosted instance with hosted APIcast. When using self-managed APIcast or on-premises instance, some minor adjustments might be needed.

    Preparing a very simple Jenkins Pipeline to deploy your API

    On your Jenkins Master, create a new Pipeline and initiate the Pipeline scripts with some global variables (that you can later promote as pipeline parameters):

    def targetSystemName = "saas-usecase-apikey"
    def targetInstance = "3scale-instance"
    def privateBaseURL = "http://echo-api.3scale.net"
    def testUserKey = "azerty1234567890"
    def developerAccountId = "john"
    def publicStagingBaseURL = null
    def publicProductionBaseURL = null

    Those variables map directly to the well-known concepts of 3scale:

    • targetSystemName is the identifier (system_name) of the service to be created.
    • targetInstance is the name of the toolbox remote that you created above.
    • privateBaseURL is the Private Base URL of the service.
    • testUserKey is the User Key/API Key that will be used to perform an end-to-end test.
    • developerAccountId is the identifier of the default "Developer" account (or the username of its admin: john).
    • publicStagingBaseURL is the Public Staging Base URL of the service.
    • publicProductionBaseURL is the Public Production Base URL of the service.

    Note: If you are using self-managed APIcast or an on-premise installation of 3scale, you would need to give a proper value to the publicStagingBaseURL and publicProductionBaseURL variables.

    Jenkins Pipeline stages to deploy your API

    In this section, we will implement the pipeline stages described in the previous article: 5 principles for deploying your API from a CI/CD pipeline.

    Fetch the OpenAPI specification file

    Add a pipeline stage to fetch your OpenAPI specification file and provide it as a ConfigMap on OpenShift:

    node() {
      stage("Fetch OpenAPI") {
        sh """
        curl -sfk -o swagger.json https://raw.githubusercontent.com/microcks/api-lifecycle/master/beer-catalog-demo/api-contracts/beer-catalog-api-swagger.json
        oc delete configmap openapi --ignore-not-found
        oc create configmap openapi --from-file="swagger.json"
        """
      }

    The OpenAPI specification contains the specifications needed to provision the API contract in 3scale:

    • Service metadata such as the name, version, maintainer, etc.
    • The payload schema.
    • The list of operations.
    • The security scheme used to secure the service.

    Import the OpenAPI Specification file

    Add a pipeline stage that uses 3scale toolbox to import the OpenAPI specification file into 3scale:

      stage("Import OpenAPI") {
        def tooboxArgs = [ "3scale", "import", "openapi", "-d", targetInstance, "/artifacts/swagger.json", "--override-private-base-url=${privateBaseURL}", "-t", targetSystemName ]
        if (publicStagingBaseURL !=null) {
          tooboxArgs += "--staging-public-base-url=${publicStagingBaseURL}"
        }
        if (publicProductionBaseURL !=null) {
          tooboxArgs += "--production-public-base-url=${publicProductionBaseURL}"
        }
        runToolbox(tooboxArgs)
      }

    This stage uses some groovy sugar to dynamically set the toolbox command-line arguments if the Public Staging or Production Base URLs are set.

    Create an application plan and an application

    Add pipeline stages that use toolbox to create a 3scale application plan and an application:

      stage("Create an Application Plan") {
        runToolbox([ "3scale", "application-plan", "apply", targetInstance, targetSystemName, "test", "-n", "Test Plan", "--default" ])
      }
    
      stage("Create an Application") {
        runToolbox([ "3scale", "application", "apply", targetInstance, testUserKey, "--account=${developerAccountId}", "--name=Test Application", "--description=Created by Jenkins", "--plan=test", "--service=${targetSystemName}" ])
      }

    Run the end-to-end tests

    Add a stage that uses toolbox to run your end-to-end tests. To run the end-to-end tests when using 3scale hosted instances, you must fetch the proxy definition to extract the staging public URL; otherwise, you can directly reuse the publicStagingBaseURL variable defined above:

      stage("Run integration tests") {
        if (publicStagingBaseURL == null) {
          def proxyDefinition = runToolbox([ "3scale", "proxy", "show", targetInstance, targetSystemName, "sandbox" ])
          def proxy = readJSON text: proxyDefinition
          publicStagingBaseURL = proxy.content.proxy.sandbox_endpoint
        }
    
        sh """
        echo "Public Staging Base URL is ${publicStagingBaseURL}"
        echo "userkey is ${testUserKey}"
        curl -vfk ${publicStagingBaseURL}/beer -H 'api-key: ${testUserKey}'
        curl -vfk ${publicStagingBaseURL}/beer/Weissbier -H 'api-key: ${testUserKey}'
        curl -vfk ${publicStagingBaseURL}/beer/findByStatus/available -H 'api-key: ${testUserKey}'
        """
      }

    Promote the configuration to the production gateway

    Each 3scale service has two public URLs: one named "staging" and one named "production." The staging URL is used to test the settings before actually applying the configuration. When the configuration is promoted, it is applied to the "production" gateway atomically.

      stage("Promote to production") {
       runToolbox([ "3scale", "proxy", "promote", targetInstance,  targetSystemName ])
      }
    }
    

    Use the 3scale toolbox to deploy your API from a Jenkins Pipeline

    Congratulations! You just deployed your API from a Jenkins Pipeline. The complete pipeline can be found here for reference.

    This pipeline is far from perfect; nevertheless, it provides a solid basis for use in your pipelines. In the next article of this blog post series, we will discuss how some shortcomings of this pipeline can be enhanced: read Using the 3scale toolbox Jenkins Shared Library.

    Read more

    • 5 principles for deploying your API from a CI/CD pipeline
    • 3scale toolbox: Deploy an API from the CLI
    • Using the 3scale toolbox Jenkins Shared Library
    Last updated: January 14, 2022

    Recent Posts

    • How to run a fraud detection AI model on RHEL CVMs

    • How we use software provenance at Red Hat

    • Alternatives to creating bootc images from scratch

    • How to update OpenStack Services on OpenShift

    • How to integrate vLLM inference into your macOS and iOS apps

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue

    OSZAR »