Invoke FunctionGraph Function from FunctionGraph using Token

This page demonstrates how to call a FunctionGraph implemented in PHP from another FunctionGraph function using API calls and token provided by an agency of Agency Type Cloud Service for Cloud Service FunctionGraph Service with permission to invoke FunctionGraph. for authentication.

See: Invoking FunctionGraph Event Function using API Calls for more details on how to use the REST API.

Prerequisites

  1. URN of Function to be called. In this example the code of the function to be called is:

    <?php
    
    function handler($event, $context) {
        $logger = $context->getLogger();
        $logger->info("Function name: " . $context->getFunctionName());
    
        return [
            "statusCode" => 200,
            "isBase64Encoded" => false,
            "body" => json_encode($event),
            "headers" => [
                "Content-Type" => "application/json"
            ]
        ];
    }
    

    Note

    Ensure that the function and the subfunction are created in the same region.

  2. An agency of Agency Type Cloud Service for Cloud Service FunctionGraph Service with permission to invoke FunctionGraph.

    The permission policy should contain following policy statement:

    {
      "Version": "1.1",
      "Statement": [
        {
          "Action": [
            "functiongraph:function:invokeAsync*",
            "functiongraph:function:invoke"
            ],
          "Effect": "Allow"
        }
      ]
    }
    

    or use an agency with default permission FunctionGraph CommonOperations.

    Note

    The permissions shown above are for demonstration purpose. Please follow the principle of least privilege when creating the permission policy for the agency.

    e.g. to grant permission to invoke only specific functions, the policy statement should be like:

    {
      "Version": "1.1",
      "Statement": [
        {
          "Action": [
            "functiongraph:function:invokeAsync*",
            "functiongraph:function:invoke"
            ],
          "Effect": "Allow",
          "Resource": [
            "RESOURCE_PATH"
          ]
        }
      ]
    }
    

    where “RESOURCE_PATH” is in format

    FunctionGraph:::function:group/function name
    

    By adding Function name to the end of the generated prefix, you can define a specific path.

    An asterisk * is allowed to indicate any function.

    For example, FunctionGraph:*:*:function:default/* indicates any function in the default group.

    For more details, see Policy Syntax in Identity and Access Management User Guide.

    (Remark: changing the permission policy may take some time to take effect.)

Coding

Create a function with following content to call another FunctionGraph function:

<?php

// Sample code to invoke a FunctionGraph function from another FunctionGraph function
// using "Token" from an agency and send it to the target FunctionGraph function
// defined as CALL_FG_URN in the user data.
// This example uses Guzzle for the HTTP request.

require __DIR__ . '/../vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request as HttpRequest;

function handler($event, $context)
{

  $logger = $context->getLogger();

  $callFgUrn = $context->getUserData('CALL_FG_URN');
  $logger->info('Starting invocation of FunctionGraph function: ' . $callFgUrn);

  $token = $context->getToken();

  // get region from the function URN, default to 'eu-de' if not available
  $region = $callFgUrn ? explode(':', $callFgUrn)[2] : 'eu-de';

  $fgEndpoint = "https://functiongraph.{$region}.otc.t-systems.com";

  // get Project ID from environment variable, default to empty string if not available
  $projectId = getenv('RUNTIME_PROJECT_ID') ?: '';
  $invokeUri = $fgEndpoint . '/v2/' . $projectId . '/fgs/functions/' . $callFgUrn . '/invocations';

  $payload = json_encode([
    'key' => 'Hello FunctionGraph',
  ], JSON_THROW_ON_ERROR);

  $headers = [
    'Content-Type' => 'application/json;charset=utf8',
    'X-Auth-Token' => $token,
  ];

  $client = new Client([
    'verify' => false,
    'timeout' => 30,
  ]);

  $httpRequest = new HttpRequest('POST', $invokeUri, $headers, $payload);
  $response = $client->send($httpRequest);
  $responseBody = (string) $response->getBody();

  $logger->info('Response: ' . $responseBody);
  $logger->info('Response status code: ' . $response->getStatusCode());

  if ($response->getStatusCode() >= 400) {
    throw new RuntimeException(
      'Backend request failed with status ' . $response->getStatusCode() . ': ' . $responseBody
    );
  }

  return $responseBody;
}

Create a composer.json file with following content:

{
  "name": "opentelekomcloud-community/invoke-fg2fg-guzzle_token",
  "description": "Samples on how to invoke FunctionGraph from FunctionGraph functions using Token and Guzzle",
  "license": "Apache-2.0",
  "type": "project",
  "require": {
    "guzzlehttp/guzzle": "^7.0"
  },
   "archive": {
    "exclude": [
      "Makefile"
    ]
  },
  "config": {
    "archive-format": "zip",
    "optimize-autoloader": true
  }
}

Create a makefile with following content:

# create a zip package of the function code for deployment
# based on composer.json archive settings
create_package:
  # install production dependencies without development dependencies
  composer install --no-dev --prefer-dist
  # create a code.zip archive of the production dependencies
  composer archive --format=zip --file=code
  # reinstall all dependencies including development dependencies
  composer install

.PHONY: create_package

Deployment

Create a deployment package using make create_package command and deploy the package to FunctionGraph using the console as an event function from scratch using PHP 8.3.

Configure the function:

  • set the handler name as src/index.handler.

  • specify an agency with permission to invoke FunctionGraph

  • and set the URN of the function to be called as environment variable with key CALL_FG_URN.

Testing

Create a test event based on Blank Template and click Test.

Execution Result on the right should show a successful execution and the function set in the CALL_FG_URN environment variable should have a new invoke request in its Monitoring.