Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-68309

Duplicate Payloads Calling Simultaneously In Parallel Steps

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not A Defect
    • Icon: Major Major
    • http-request-plugin
    • None

      We have a pipeline in which we are running parallel steps. One of the things that we do in the parallel steps is send a POST request to an API. We have found that when multiple calls occur simultaneously, although each call should have a unique payload, they all use the same payload. This was tested by adding in a random sleep before they make the API call and saw the calls work as we expect. 

      A minimal Jenkinsfile to test the issue can be found below, note that the API we are calling is internal and so I cannot provide the URL to it in my sample.  It is simply a POST endpoint that takes in a string as the body.

       

      def randomNumber (int lowerLimit, int upperLimit) {
        Random rand = new Random()
        random_number = rand.nextInt(upperLimit+lowerLimit)
        return random_number
      }
      def getAllTerraformsExecutionParallelSteps(Map PipelineResourcesV2, Boolean ValidateOnly=false) {
        def steps = [:]
        for (int x=0; x < PipelineResourcesV2.terraforms.size(); x++) {
          def currentTerraform = PipelineResourcesV2.terraforms[x]
          if (currentTerraform.name != 'EnvironmentDefaults') {
            steps[currentTerraform.name] = {
              currentTerraform["outputs"] = invokeJob(PipelineResourcesV2, currentTerraform, ValidateOnly, 0, true)
            }
          }
        }
        return steps
      }
      def invokeJob(Map pipelineResources, Map terraformMap, Boolean validateOnly=false, Integer quietPeriod=0, Boolean wait=true) {
        //terraformMap required values: name, provider, configuration.path, configuration.region
        echo "Invoking for name: ${terraformMap.name} provider: ${terraformMap.provider} path: ${terraformMap.configuration.path} validateOnly: ${validateOnly}"
        def logVerb='Applying'
        if (validateOnly) {
          logVerb='Validating'
        }
        try{
          // uncomment the line below to test with random sleep
          //sleep randomNumber(1,20)
          addLogMessage("INFO", "${logVerb} Terraform for ${terraformMap.name}")
          return null
        }catch(e){
          error "Failed to execute: ${e}"
        }
      }
      def callAPI(String method, String uriStem, String validResponseCodes = '200', String requestBody = null) {
        httpRequestParameters = [
          'url': '{baseURL}' + uriStem,
          'httpMode': method,
          'validResponseCodes': validResponseCodes,
          'authentication': {credentials},
          'consoleLogResponseBody': true
        ]  if(requestBody){
          httpRequestParameters['requestBody'] = requestBody
          httpRequestParameters['contentType'] = 'APPLICATION_JSON'
        }  try {
          retry(5){
            httpRequest(httpRequestParameters)
          }
        }
        catch(Exception e) {
          throw e
        }
      }
      def addLogMessage(String level = 'Info', String message){
        callAPI('POST', "{path}", '200', "\"${message}\"")
      }
      node {
          stage('Test') {
              
              def PipelineResourcesV2 = readJSON(text: '{"terraforms":[{"name":"EnvironmentDefaults","provider":"AwsTerragruntV2","configuration":{"region":"","path":""},"outputs":{}},{"provider":"AwsTerragruntV2","name":"IISV1","configuration":{"region":"","path":"","terragruntJsonConfig":{"terraform":{},"inputs":{"infrastructure_name":"WINDOWS-DOTNET","domain_name":"","application_name":"IISV1","instances":[""]}}}},{"provider":"AwsTerragruntV2","name":"DOTNETWEBV1","configuration":{"region":"","path":"","terragruntJsonConfig":{"terraform":{},"inputs":{"infrastructure_name":"LINUX-DOTNET","domain_name":"","application_name":"DOTNETWEBV1","instances":[""]}}}},{"provider":"AwsTerragruntV2","name":"TOMCATV1","configuration":{"region":"","path":"","terragruntJsonConfig":{"terraform":{},"inputs":{"infrastructure_name":"WINDOWS-JAVA","domain_name":"","application_name":"TOMCATV1","instances":[""]}}}},{"provider":"AwsTerragruntV2","name":"TOMCATV2","configuration":{"region":"","path":"","terragruntJsonConfig":{"terraform":{},"inputs":{"infrastructure_name":"LINUX-JAVA","domain_name":"","application_name":"TOMCATV2","instances":[""]}}}}]}')
              def stepsForTerraformValidation = getAllTerraformsExecutionParallelSteps(PipelineResourcesV2, true)
              parallel stepsForTerraformValidation
          }
      }

            janario Janario Oliveira
            butter1484 Brady Shober
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: