Skip to content

Playground feature catalog #11592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft

Playground feature catalog #11592

wants to merge 10 commits into from

Conversation

steffyP
Copy link
Member

@steffyP steffyP commented Sep 27, 2024

Motivation

With the requirement of having more up-to-date feature documentation, this PR is exploring one approach, where we the documentation will live inside the code base.

This is only a first PoC. It includes the entire feature catalog for KMS, and only a few selected features for cloudwatch.
We added a script that is creating a json-output with the data from this PoC.

Basic Idea

For this PoC the main idea is to have python classes that will document certain features.
E.g. it provides base class ServiceFeature, which will then be enhanced by service specific features, like KmsFeature. The KmsFeatures in turn can further be split into sub classes, and you can add as many class-attributes as required (e.g. general docs description, limitations, implementation status etc).

This part of the feature catalog documentation is static, e.g. the classes itself already document the behavior.

Decorators

The classes can be used as decorators for functions or api-operations. In that case, we can collect the data dynamically, e.g. by iterating through all service-packages and collect the function/operation names and map them to the specific features.

In a similar way, we are suggesting two approaches to document specific limitations for an api-operation.
This could be useful in case we use this docs also for creating the api-coverage docs, and also if you have some specific limitations that you feel shouldn't be part of the python-docs limitation, as they are very specific.

The suggested approaches:

1. Using sub classes for each limitation

There is a class ApiCoverage, which should be used a base class for any additional api-limitation that you want to document, e.g.

class CreateKey(ApiCoverage):
"""
One suggestions on how to track specific api-operation limitations:
Alternative solution would be using the ApiLimitation (file feature_catalog/api_limitation.py), which provides a more generic way
of doing so
"""
general_docs: str = "Creates an AWS KMS key."
implementation_status: ImplementationStatus = ImplementationStatus.PARTIALLY_IMPLEMENTED
support_type: SupportStatus = SupportStatus.SUPPORTED
limitations: list = [
"Status 'Updating' is not supported.",
]

Downside: for every limitation, you have to create a new subclass, maintaining may be more tedious
Advantage: code is not cluttered too much in case there are a lot of limitations

2. Using a generic class to document limitation

Using a decorator ApiLimitation that takes an input argument limitation that can be set dynamically for as many operations as required.

Downside: if there are a lot of limitations, this may clutter the code (one way to improve this could be to use string constants in that case, that are defined in another file)
Advantage: no need to recreate subclasses

Here is a sample on how this would be applied for both approaches:

@handler("CreateKey", expand=False)
@kms_feature.Provisioning
@kms_api.CreateKey
@ApiLimitation(limitation="Status 'Updating' is not supported.")
def create_key(
self,
context: RequestContext,
request: CreateKeyRequest = None,
) -> CreateKeyResponse:
key = self._create_kms_key(context.account_id, context.region, request)
return CreateKeyResponse(KeyMetadata=key.metadata)

General Evaluation

Advantages:

  • code and documentation are close, whenever there is a minor or major label on the PR we can assume that the docs should also be adapted
  • Flexible model, we can create machine-readable output from the data and then further use it to create documents, official docs etc
  • api-operations or functions can be marked to be part of a feature, but it's not required
  • we can add feature documentation for different provider implementations (e.g. v1, v2)

Disadvantages:

  • using decorator pattern feels a bit abusive, as we are not really adding functionality to the code
  • keeping things up-to-date may still be tricky

Further improvement ideas

  • define json-schema and validate that certain attributes are part of each feature definition
    • this could be helpful when we want to further parse the output for docs generation etc.
    • could be run in a workflow

Changes

  • PoC for feature catalog
  • added script playground.py to parse the data:
{
  "ServiceFeature": {
    "CloudWatchFeature": {
      "docs": {
        "implementation_status": "ImplementationStatus.PARTIALLY_IMPLEMENTED"
      },
      ....
      "Alarm": {
        "docs": {
          "general_docs": "Alarms are used to set thresholds for metrics and trigger actions",
          "supported": "SupportStatus.SUPPORTED_PARTIALLY_EMULATED",
          "implementation_status": "ImplementationStatus.PARTIALLY_IMPLEMENTED",
          "aws_docs_link": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html"
        },
        "CompositeAlarm": {
          "docs": {
            "supported": "SupportStatus.SUPPORTED_MOCKED_ONLY",
            "aws_docs_link": "https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Create_Composite_Alarm.html"
          },
          "operations": [
            "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.put_composite_alarm"
          ]
        },
        "MetricAlarm": {
          "docs": {
            "supported": "SupportStatus.SUPPORTED",
            "supported_triggers": [
              "SNS",
              "Lambda"
            ]
          },
          "operations": [
            "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.put_metric_alarm"
          ]
        },
        "operations": [
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.delete_alarms",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.describe_alarm_history",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.describe_alarms",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.describe_alarms_for_metric",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.disable_alarm_actions",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.enable_alarm_actions",
          "localstack.services.cloudwatch.provider_v2.CloudwatchProvider.set_alarm_state",
          "localstack.services.cloudwatch.provider_v2.delete_alarms_helper"
        ]
      }
    },
    "KMSFeature": {
      "docs": {
        "implementation_status": "ImplementationStatus.PARTIALLY_IMPLEMENTED"
      },
        "Provisioning": {
          "docs": {
            "general_docs": "Manage the creation and modification of the keys.",
            "implementation_status": "ImplementationStatus.FULLY_IMPLEMENTED",
            "support_type": "SupportStatus.SUPPORTED",
            "aws_docs_link": "https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html",
            "api_operations": [
              "CreateKey"
            ]
          },
          "operations": [
            "localstack.services.kms.provider.KmsProvider.create_key",
            "localstack.services.kms.provider.KmsProvider.update_key_description"
          ],
          "api_limitations": {
            "localstack.services.kms.provider.KmsProvider.create_key": "Status 'Updating' is not supported."
          }
        },
    ...
    }

@steffyP steffyP added the semver: patch Non-breaking changes which can be included in patch releases label Sep 27, 2024
@steffyP steffyP added this to the Playground milestone Sep 27, 2024
@steffyP steffyP self-assigned this Sep 27, 2024
Copy link

github-actions bot commented Sep 27, 2024

LocalStack Community integration with Pro

    2 files  ± 0      2 suites  ±0   1h 37m 48s ⏱️ +31s
3 478 tests +28  3 061 ✅ +14  417 💤 +14  0 ❌ ±0 
3 480 runs  +28  3 061 ✅ +14  419 💤 +14  0 ❌ ±0 

Results for commit 9609dc3. ± Comparison against base commit 6f16877.

♻️ This comment has been updated with latest results.

Comment on lines +5 to +33
class SupportStatus(Enum):
"""
Indicates the support on LocalStack in regard to the actual implementation
E.g.
SUPPORTED means that everything is behaving as on AWS
SUPPORTED_MOCKED_ONLY means that the response is the same as on AWS, but there is no actual behavior behind it (e.g. no database created)
SUPPORTED_PARTIALLY_EMULATED means that there is some kind of emulation, but there may be parts missing
NOT_SUPPORTED means this is not implemented at all on LS
"""

SUPPORTED = 1
SUPPORTED_MOCKED_ONLY = 2
SUPPORTED_PARTIALLY_EMULATED = 3
NOT_SUPPORTED = 4


class ImplementationStatus(Enum):
"""
Indicates implementation status on LS
E.g.
FULLY_IMPLEMENTED means that all (important?) operations are implemented
PARTIALLY_IMPLEMENTED means some selected operations are implemented
EXPERIMENTAL means that there is some implementation, but this feature is still higly experimental
"""

FULLY_IMPLEMENTED = 1
PARTIALLY_IMPLEMENTED = 2
EXPERIMENTAL = 3

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mainly for testing purpose, I don't think this is the best classification as it seems a bit confusing

)


class CreateKey(ApiCoverage):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this approach was suggested by @sannya-singal to document additional limitations.
However, we also iterated over it, and came up with a ApiLimitation decorator that could take the limitation as input, which may be more practical solution as we don't need to setup subclasses.

implementation_status: ImplementationStatus = ImplementationStatus.FULLY_IMPLEMENTED
support_type: SupportStatus = SupportStatus.SUPPORTED
aws_docs_link: str = "https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html"
api_operations: list = ["CreateKey"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just one suggestion on how to include api_operations.
With the usage as decorators, however, we have shown that we can also link the decorated functions back to the feature-catalog-mapping, which makes this information redundant.

Comment on lines +109 to +113
@cloudwatch_feature.Alarm
def delete_alarms_helper():
pass


Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just added this to verify that we can also decorate functions, and that the data will be collected as well.

Comment on lines +374 to +375
@kms_api.CreateKey
@ApiLimitation(limitation="Status 'Updating' is not supported.")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both, @kms_api.CreateKey and @ApiLimitation are used as an example to track api-specific limitations.
The playground.py script only considers the ApiLimitation, while in the playgrond_kms_api_limitation.py we collect the data from the former decorator.

Comment on lines -740 to +759
@handler("GenerateDataKeyPair")
@kms_feature.Data
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the @handler decorator without any parameter input somehow interfered with the asf_utils-tests, I didn't investigate too much and just removed for now. handlers with input-parameter are handled correctly.

Copy link
Contributor

@sannya-singal sannya-singal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice to see everything coming together in one PR 🎉 I'm a bit biased towards the implementation here since I worked on it, so I'll leave the feedback to Dominik :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver: patch Non-breaking changes which can be included in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants