go-to-k

new-provider

Scaffold a new SDK Provider for a given AWS resource type (e.g., AWS::SES::EmailIdentity). Creates provider file, registers it, and generates test boilerplate.

go-to-k 147 12 Updated 4w ago
GitHub

Install

npx skillscat add go-to-k/cdkd/new-provider

Install via the SkillsCat registry.

SKILL.md

New Provider Scaffold

You are scaffolding a new SDK Provider for cdkd.

Input

The user provides an AWS resource type like AWS::SES::EmailIdentity.

Steps

  1. Parse the resource type to determine:

    • Service name (e.g., SES)
    • Resource name (e.g., EmailIdentity)
    • AWS SDK client package (e.g., @aws-sdk/client-ses)
    • Provider file name (e.g., ses-email-identity-provider.ts)
  2. Check if provider already exists in src/provisioning/providers/ and src/provisioning/register-providers.ts.

  3. Read an existing provider as reference for the pattern. Use a simple one like src/provisioning/providers/ssm-parameter-provider.ts or src/provisioning/providers/logs-log-group-provider.ts.

  4. Read the AWS SDK docs or infer the API calls needed:

    • CREATE: Which API creates this resource? What does it return (physical ID, attributes)?
    • UPDATE: Which API updates this resource?
    • DELETE: Which API deletes this resource?
    • getAttribute: Which attributes might be needed for Fn::GetAtt?
    • import: Which API verifies a resource exists by physical id (Get* / Describe* / Head*), and which List* + ListTags* (or equivalent) lookup-by-tag pair lets you find a resource by its aws:cdk:path tag? See "Import method" under step 5 — most providers follow the same shape.
  5. Create the provider file at src/provisioning/providers/{service}-{resource}-provider.ts:

    • Import the AWS SDK client and commands
    • Implement ResourceProvider interface (create, update, delete, getAttribute, import)
    • Take clients from getAwsClients(), or build your own SDK client with ...ambientClientDefaults() (../../utils/ambient-client-defaults.js) spread FIRST — a bare awsClientDefaults() drops a library caller's explicit credentials and fails ambient-client-defaults-fence.test.ts (#3588)
    • Follow ESM import conventions (.js extension)
    • Return proper physicalId and attributes from create

    Import method — copy the shape from a similar provider rather than
    writing it from scratch: s3-bucket-provider.ts for a tag-ARRAY service,
    lambda-function-provider.ts for a tag-MAP one, kms-provider.ts for a
    service with no template name property. The shape is: resolve an explicit
    physical id first (resolveExplicitPhysicalId(input, '<NameField>'), i.e.
    the --resource override or Properties.<NameField>) and verify it with a
    Get / Head / Describe call; otherwise, with input.cdkPath present,
    walk the service's List* paginator, fetch tags per resource and match
    aws:cdk:path through matchesCdkPath (CDK_PATH_TAG in
    ../import-helpers.js).

    Notes:

    • Return null (not throw) when the resource is not found — caller
      treats this as "skipped" rather than failure.
    • attributes: {} is fine; Fn::GetAtt reconstructs missing
      attributes at deploy time via constructAttribute (see
      src/deployment/intrinsic-function-resolver.ts).
    • For services whose ListTags returns a Record<string,string>
      map instead of a Tag[] array (Lambda, SQS), read the value at
      key CDK_PATH_TAG directly instead of going through
      matchesCdkPath.
    • For services with NO template-supplied name field (KMS Key,
      CloudFront Distribution), skip step 1's name fallback — only
      the explicit-override path and tag lookup apply.
    • Some services don't support tagging or ListTags requires extra
      IAM. If tag lookup is impractical, document that limitation in
      the method's doc comment and rely on --resource overrides.
  6. Register the provider in src/provisioning/register-providers.ts:

    • Add import for the new provider
    • Add registry.register('AWS::Service::Resource', new ServiceResourceProvider()) in registerAllProviders()
  7. Create test file at tests/unit/provisioning/providers/{service}-{resource}-provider.test.ts:

    • Mock the AWS SDK client
    • Test create (verify API call, physicalId, attributes)
    • Test update (verify API call)
    • Test delete (verify API call)
    • Test delete idempotency (not-found treated as success)
    • Test import explicit-override path (knownPhysicalId verified, attrs returned)
    • Test import tag-based lookup (List + ListTags + cdkPath match)
    • Test import not-found (returns null, does not throw)
  8. Check if @aws-sdk/client-{service} is already in package.json. If not, tell the user to run pnpm add @aws-sdk/client-{service}.

  9. Run typecheck, lint, build, and tests to verify everything works.

  10. Create integration test by invoking /new-integ with a test name based on the resource type (e.g., ses-email-identity). The integ test should create a minimal CDK stack using the new resource type.

Important

  • Follow the exact patterns used by existing providers
  • Always use .js extension in imports (ESM)
  • Physical ID should match what CloudFormation uses for that resource type
  • Include delete idempotency (not-found errors treated as success)
  • Do NOT add the SDK client package yourself; tell the user if it's missing
  • Always create an integration test after the provider is implemented