tmforum-oda / oda-canvas

Apache License 2.0
18 stars 49 forks source link

Dependent API: Build Canvas.Info API service #289

Open LesterThomas opened 1 month ago

LesterThomas commented 1 month ago

Description

This is a sub-issue from issue #208

This is to build an API service into the Canvas that Components can call to discover the location and details of dependent APIs. A component declares its requirement for Dependent APIs as part of its component envelope; The Canvas Dependent API Operator configures these dependencies. Finally the component calls this service at a fixed url info.canvas.svc.cluster.local.

The service implements the Service Inventory API API and should return to each component just the dependent APIs that the component has been authorized to call.

ferenc-hechler commented 1 month ago

Do we have a Bootstrap issue? How does a component authenticate against the info service?

LesterThomas commented 1 month ago

Do we have a Bootstrap issue? How does a component authenticate against the info service?

When you deploy a component, the identity management operator creates a System User for that component in the IDM. The component makes outbound calls by using the ClientID and Secret for that system user (and getting a token from Oauth2 API).

We need to decide how the component gets the clientID / Secret, but the. The call to Canvas.Info should be ok. The canvas.info will get details about the calling component from the token.

LesterThomas commented 1 month ago

There is an example of the Service Inventory payload in the Example Reference ProductCatalog component.

The serviceCharacteristic must have a dependencyName characteristic that matches the depenentAPI name declared in the component specification (in this example downstreamproductcatalog).

The component can then use url characteristic to call the dependent API.

The component calls the API using its own system user clientID/secret that was created as part of the component deployment. It uses the clientID/secret against the Oauth 2.0 endpoint to get a token, and then uses this token in the API call. The Canvas.Info service will use this token to determine who the calling component is and return API services specific to that component.

ferenc-hechler commented 2 weeks ago

Together with @brian-burton we created a sketch how the Data Flow looks like

image-2024-08-28-15-50-56-990

Exposed- and DependentAPI Custom-Resources are created from the Component-Operator. The DependentAPI-Operator (triggered by the custom resource) resolves the endpoint based on the specification given in the DependentAPI Custom-Resource.

After successful discovery of the endpoint, the target information is stored in the Service-Inventory-API, where it can be queried from the consuming ODA component (Product Order).

ferenc-hechler commented 2 weeks ago

Tasks for implementing this workflow (without any auth):

ferenc-hechler commented 5 days ago

@LesterThomas is there an updated version of the payload which also contains the component name?

The DependentAPI Operator will create an entry in the service inventory which is valid for one component in combination with the dependencyName.

https://github.com/tmforum-oda/reference-example-components/blob/master/source/ProductCatalog/tests/standalone-canvas-info-service/example-API-service.json

A proposal:

{
    "serviceType": "API",
    "name": "Acme partner catalog",
    "description": "Implementation of TMF620 Product Catalog Management Open API",
    "state": "active",
    "serviceCharacteristic": [
        {
            "name": "componentName",
            "valueType": "string",
            "value": "acme-productinventory",
            "@type": "StringCharacteristic"
        },
        {
            "name": "dependencyName",
            "valueType": "string",
            "value": "downstreamproductcatalog",
            "@type": "StringCharacteristic"
        },
        {
            "name": "url",
            "valueType": "string",
            "value": "http://localhost/acme-productcatalogmanagement/tmf-api/productCatalogManagement/v4",
            "@type": "StringCharacteristic"
        },
        {
            "name": "OAS Specification",
            "valueType": "string",
            "value": "https://raw.githubusercontent.com/tmforum-apis/TMF620_ProductCatalog/master/TMF620-ProductCatalog-v4.0.0.swagger.json",
            "@type": "StringCharacteristic"
        }
    ],
    "serviceSpecification": {
        "id": "1",
        "name": "API",
        "version": "1.0.0",
        "@type": "ServiceSpecification",
        "specCharacteristic": [
            {
                "name": "componentName",
                "valueType": "string",
                "description": "The name of the component which wants to consume the API service. The component name is normally available in the environment vaiable COMPONENT_NAME",
                "@type": "StringCharacteristic"
            },
            {
                "name": "dependencyName",
                "valueType": "string",
                "description": "The dependency name that this API service matches. The dependency name is set in the Component Specification",
                "@type": "StringCharacteristic"
            },
            {
                "name": "url",
                "valueType": "string",
                "description": "The url the the API root endpoint",
                "@type": "StringCharacteristic"
            },
            {
                "name": "OAS Specification",
                "valueType": "string",
                "description": "The url to the Open API Speciofication for this API",
                "@type": "StringCharacteristic"
            }
        ]
    },
    "@type": "Service"
}