code: def create_or_update_stack(
      args,
      *,
      client,
      stack_name,
      template_url=None,
      template_body=None,
      params=None,
  ):
      kwargs = {
          "StackName": stack_name,
          "Capabilities": [
              "CAPABILITY_IAM",
              "CAPABILITY_NAMED_IAM",
              "CAPABILITY_AUTO_EXPAND",
          ],
      }
      if template_url:
          kwargs["TemplateURL"] = template_url
      if template_body:
          kwargs["TemplateBody"] = template_body
      if params:
          kwargs["Parameters"] = params
  
      if stack_exists(args, stack_name=stack_name):
          print(f"Stack {stack_name} already exists. Updating...")
          try:
              response = client.update_stack(**kwargs)
              return {"StackName": stack_name, "Action": "update"}
          except botocore.exceptions.ClientError as e:
              if e.response["Error"][
                  "Code"
              ] == "ValidationError" and re.search(
                  "No updates are to be performed",
                  e.response["Error"]["Message"],
              ):
                  print(f"No update was made to {stack_name}")
                  return {"StackName": stack_name, "Action": "noop"}
              else:
                  raise e
      else:
          kwargs.update(
              {
                  "OnFailure": "ROLLBACK",
                  "EnableTerminationProtection": False,
              }
          )
          response = client.create_stack(**kwargs)
          return {"StackName": stack_name, "Action": "create"}
  
imports: import re
  import boto3
  import botocore
label_desc: Use image node_id 2 for calling a global function with example usage: create_or_update_stack(args) and returns: dict, dict, dict