diff --git a/scenarios/basics/guardduty/SPECIFICATION.md b/scenarios/basics/guardduty/SPECIFICATION.md new file mode 100644 index 00000000000..2c8c666bbfc --- /dev/null +++ b/scenarios/basics/guardduty/SPECIFICATION.md @@ -0,0 +1,87 @@ +# Amazon GuardDuty Specification + +This document contains a draft proposal for a Code Example for *Amazon GuardDuty Basics Scenario*, generated by the Code Examples SpecGen AI tool. The specifications describe a potential code example scenario based on research, usage data, service information, and AI-assistance. The following should be reviewed for accuracy and correctness before proceeding on to a final specification. + +### Relevant documentation + +* [Getting started with GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_settingup.html) +* [What is Amazon GuardDuty?](https://docs.aws.amazon.com/guardduty/latest/ug/what-is-guardduty.html) +* [Amazon GuardDuty API Reference](https://docs.aws.amazon.com/guardduty/latest/APIReference/Welcome.html) +* [GuardDuty Pricing](https://aws.amazon.com/guardduty/pricing/) + +### API Actions Used + +* [CreateDetector](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_CreateDetector.html) +* [GetDetector](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_GetDetector.html) +* [ListDetectors](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_ListDetectors.html) +* [CreateSampleFindings](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_CreateSampleFindings.html) +* [ListFindings](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_ListFindings.html) +* [GetFindings](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_GetFindings.html) +* [DeleteDetector](https://docs.aws.amazon.com/guardduty/latest/APIReference/API_DeleteDetector.html) + +## Proposed example structure + +The details below describe how this example would run for the customer. It includes a Hello service example (included for all services), and the scenario details. The scenario code would also be presented as Action snippets, with a code snippet for each SDK action. + +### Hello + +The Hello example is a separate runnable example. - Set up the GuardDuty service client - Check if GuardDuty is available in the current region - List any existing detectors + +## Scenario + +#### Setup + +* Create a GuardDuty detector to enable threat detection +* Verify the detector is successfully created and active +* Display detector configuration and status + +#### Sample Findings Generation + +* Generate sample findings to demonstrate GuardDuty capabilities +* List the generated sample findings +* Display finding details including severity and type + +#### Findings Management + +* Retrieve detailed information about specific findings +* Filter findings by severity level +* Display finding metadata and threat information + +#### Cleanup + +* Archive or acknowledge sample findings +* Optionally disable the detector (with user confirmation) +* Clean up resources created during the example + +## Errors + +SDK Code examples include basic exception handling for each action used. The table below describes an appropriate exception which will be handled in the code for each service action. + +|Action |Error |Handling | +|--- |--- |--- | +|`CreateDetector` |BadRequestException |Validate input parameters and notify user of invalid configuration. | +|`CreateDetector` |InternalServerErrorException |Retry operation with exponential backoff. | +|`GetDetector` |BadRequestException |Validate detector ID format and existence. | +|`GetDetector` |InternalServerErrorException |Retry operation and handle service unavailability. | +|`ListDetectors` |BadRequestException |Validate pagination parameters and retry. | +|`ListDetectors` |InternalServerErrorException |Handle service errors gracefully. | +|`CreateSampleFindings` |BadRequestException |Validate detector ID and finding types. | +|`CreateSampleFindings` |InternalServerErrorException |Retry sample finding generation. | +|`ListFindings` |BadRequestException |Validate finding criteria and pagination. | +|`GetFindings` |BadRequestException |Validate finding IDs format. | +|`DeleteDetector` |BadRequestException |Confirm detector exists before deletion. | +|`DeleteDetector` |InternalServerErrorException |Handle deletion failures gracefully. | + +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`CreateDetector` |guardduty_metadata.yaml |guardduty_CreateDetector | +|`GetDetector` |guardduty_metadata.yaml |guardduty_GetDetector | +|`ListDetectors` |guardduty_metadata.yaml |guardduty_ListDetectors | +|`CreateSampleFindings` |guardduty_metadata.yaml |guardduty_CreateSampleFindings | +|`ListFindings` |guardduty_metadata.yaml |guardduty_ListFindings | +|`GetFindings` |guardduty_metadata.yaml |guardduty_GetFindings | +|`DeleteDetector` |guardduty_metadata.yaml |guardduty_DeleteDetector | +|`Amazon GuardDuty Basics Scenario` |guardduty_metadata.yaml |guardduty_Scenario | + diff --git a/scenarios/basics/inspector/SPECIFICATION.md b/scenarios/basics/inspector/SPECIFICATION.md new file mode 100644 index 00000000000..51eece5c95f --- /dev/null +++ b/scenarios/basics/inspector/SPECIFICATION.md @@ -0,0 +1,89 @@ +# Amazon Inspector Specification + +This document contains a draft proposal for an *Amazon Inspector Basics Scenario*, generated by the Code Examples SpecGen AI tool. The specifications describe a potential code example scenario based on research, usage data, service information, and AI-assistance. The following should be reviewed for accuracy and correctness before proceeding on to a final specification. + +### Relevant documentation + +* [Getting started with Amazon Inspector](https://docs.aws.amazon.com/inspector/latest/user/getting_started.html) +* [What is Amazon Inspector?](https://docs.aws.amazon.com/inspector/latest/user/what-is-inspector.html) +* [Amazon Inspector API Reference](https://docs.aws.amazon.com/inspector/v2/APIReference/Welcome.html) +* [Amazon Inspector Pricing](https://aws.amazon.com/inspector/pricing/) + +### API Actions Used + +* [Enable](https://docs.aws.amazon.com/inspector/v2/APIReference/API_Enable.html) +* [BatchGetAccountStatus](https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetAccountStatus.html) +* [ListFindings](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListFindings.html) +* [BatchGetFindingDetails](https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html) +* [ListCoverage](https://docs.aws.amazon.com/inspector/v2/APIReference/API_ListCoverage.html) +* [Disable](https://docs.aws.amazon.com/inspector/v2/APIReference/API_Disable.html) + +## Proposed example structure + +The output below demonstrates how this example would run for the customer. It includes a Hello service example (included for all services), and the scenario description. The scenario code would also be presented as Action snippets, with a code snippet for each SDK action. + +### Hello + +The Hello example is a separate runnable example. - Set up the Inspector service client - Check the current account status for Inspector - Display available scan types and regions + +## Scenario + +#### Setup + +* Enable Amazon Inspector for the account +* Verify Inspector is successfully activated +* Display account status and enabled scan types + +#### Coverage Assessment + +* List coverage statistics for EC2 instances, ECR repositories, and Lambda functions +* Display resource coverage details +* Show scanning status for different resource types + +#### Findings Management + +* List security findings across all resource types +* Filter findings by severity level (CRITICAL, HIGH, MEDIUM, LOW) +* Retrieve detailed information for specific findings + +#### Vulnerability Analysis + +* Display vulnerability details including CVE information +* Show affected resources and remediation guidance +* Filter findings by resource type (EC2, ECR, Lambda) + +#### Cleanup + +* Optionally disable Inspector scanning (with user confirmation) +* Display final account status + +## Errors + +SDK Code examples include basic exception handling for each action used. The table below describes an appropriate exception which will be handled in the code for each service action. + +|Action |Error |Handling | +|--- |--- |--- | +|`Enable` |ValidationException |Validate resource types and account permissions. | +|`Enable` |AccessDeniedException |Notify user of insufficient permissions and exit. | +|`BatchGetAccountStatus` |ValidationException |Validate account IDs format. | +|`BatchGetAccountStatus` |AccessDeniedException |Handle permission errors gracefully. | +|`ListFindings` |ValidationException |Validate filter criteria and pagination parameters. | +|`ListFindings` |InternalServerException |Retry operation with exponential backoff. | +|`BatchGetFindingDetails` |ValidationException |Validate finding ARNs format. | +|`BatchGetFindingDetails` |AccessDeniedException |Handle access denied for specific findings. | +|`ListCoverage` |ValidationException |Validate filter and pagination parameters. | +|`Disable` |ValidationException |Validate resource types for disabling. | +|`Disable` |ConflictException |Handle cases where Inspector cannot be disabled. | + +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`Enable` |inspector_metadata.yaml |inspector_Enable | +|`BatchGetAccountStatus` |inspector_metadata.yaml |inspector_BatchGetAccountStatus | +|`ListFindings` |inspector_metadata.yaml |inspector_ListFindings | +|`BatchGetFindingDetails` |inspector_metadata.yaml |inspector_BatchGetFindingDetails | +|`ListCoverage` |inspector_metadata.yaml |inspector_ListCoverage | +|`Disable` |inspector_metadata.yaml |inspector_Disable | +|`Amazon Inspector Basics Scenario` |inspector_metadata.yaml |inspector_Scenario | + diff --git a/steering_docs/dotnet-tech.md b/steering_docs/dotnet-tech.md new file mode 100644 index 00000000000..290814eaf05 --- /dev/null +++ b/steering_docs/dotnet-tech.md @@ -0,0 +1,200 @@ +# .NET Technology Stack & Build System + +## .NET 8+ Development Environment + +### Build Tools & Dependencies +- **Build System**: dotnet CLI +- **Package Manager**: NuGet +- **Testing Framework**: xUnit +- **Code Formatting**: dotnet-format +- **SDK Version**: AWS SDK for .NET v4 +- **.NET Version**: .NET 8+ + +### Common Build Commands + +```bash +# Build and Package +dotnet build SOLUTION.sln # Build solution +dotnet build PROJECT.csproj # Build specific project +dotnet clean # Clean build artifacts + +# Testing +dotnet test # Run all tests +dotnet test --filter Category=Integration # Run integration tests +dotnet test --logger trx # Run tests with detailed output + +# Execution +dotnet run # Run project +dotnet run --project PROJECT.csproj # Run specific project + +# Code Quality +dotnet format # Format code +``` + +### .NET-Specific Pattern Requirements + +#### File Naming Conventions +- Use PascalCase for class names and file names +- Service prefix pattern: `{Service}Actions.cs` (e.g., `S3Actions.cs`) +- Hello scenarios: `Hello{Service}.cs` (e.g., `HelloS3.cs`) +- Test files: `{Service}Tests.cs` + +#### Hello Scenario Structure +- **Class naming**: `Hello{Service}.cs` class with main method +- **Method structure**: Static Main method as entry point +- **Documentation**: Include XML documentation explaining the hello example purpose + +#### Code Structure Standards +- **Namespace naming**: Use reverse domain notation (e.g., `Amazon.DocSamples.S3`) +- **Class structure**: One public class per file matching filename +- **Method naming**: Use PascalCase for method names +- **Properties**: Use PascalCase for property names +- **Constants**: Use PascalCase for constants +- **Async methods**: Suffix with `Async` (e.g., `ListBucketsAsync`) + +#### Dependency Injection Patterns +```csharp + /// + /// Main entry point for the AWS Control Tower basics scenario. + /// + /// Command line arguments. + public static async Task Main(string[] args) + { + using var host = Host.CreateDefaultBuilder(args) + .ConfigureServices((_, services) => + services.AddAWSService() + .AddAWSService() + .AddAWSService() + .AddAWSService() + .AddTransient() + ) + .Build(); + + logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) + .CreateLogger(); + + wrapper = host.Services.GetRequiredService(); + orgClient = host.Services.GetRequiredService(); + stsClient = host.Services.GetRequiredService(); + + await RunScenario(); + } +``` + +#### Error Handling Patterns +```csharp +using Amazon.S3; +using Amazon.S3.Model; +using System; +using System.Threading.Tasks; + +public class ExampleClass +{ + public async Task ExampleMethodAsync() + { + var s3Client = new AmazonS3Client(); + + try + { + var response = await s3Client.ListBucketsAsync(); + // Process response + Console.WriteLine($"Found {response.Buckets.Count} buckets"); + } + catch (AmazonS3Exception e) + { + // Handle S3-specific exceptions + Console.WriteLine($"S3 Error: {e.Message}"); + Console.WriteLine($"Error Code: {e.ErrorCode}"); + throw; + } + catch (Exception e) + { + // Handle general exceptions + Console.WriteLine($"Error: {e.Message}"); + throw; + } + finally + { + s3Client?.Dispose(); + } + } +} +``` + +#### Testing Standards +- **Test framework**: Use xUnit attributes (`[Fact]`, `[Theory]`) +- **Integration tests**: Mark with `[Trait("Category", "Integration")]` +- **Async testing**: Use `async Task` for async test methods +- **Resource management**: Use `using` statements for AWS clients +- **Test naming**: Use descriptive method names explaining test purpose + +#### Project Structure +``` +src/ +├── {Service}Examples/ +│ ├── Hello{Service}.cs +│ ├── {Service}Actions.cs +│ ├── {Service}Scenarios.cs +│ └── {Service}Examples.csproj +└── {Service}Examples.Tests/ + ├── {Service}Tests.cs + └── {Service}Examples.Tests.csproj +``` + +#### Documentation Requirements +- **XML documentation**: Use `///` for class and method documentation +- **Parameter documentation**: Document all parameters with `` +- **Return documentation**: Document return values with `` +- **Exception documentation**: Document exceptions with `` +- **README sections**: Include dotnet setup and execution instructions + +### AWS Credentials Handling + +#### Critical Credential Testing Protocol +- **CRITICAL**: Before assuming AWS credential issues, always test credentials first with `aws sts get-caller-identity` +- **NEVER** assume credentials are incorrect without verification +- If credentials test passes but .NET SDK fails, investigate SDK-specific credential chain issues +- Common .NET SDK credential issues: EC2 instance metadata service conflicts, credential provider chain order + +### Build Troubleshooting + +#### DotNetV4 Build Troubleshooting +- **CRITICAL**: When you get a response that the project file does not exist, use `listDirectory` to find the correct project/solution file path before trying to build again +- **NEVER** repeatedly attempt the same build command without first locating the actual file structure +- Always verify file existence with directory listing before executing build commands + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER create examples for dotnetv3 UNLESS explicitly instructed to by the user** +- ❌ **NEVER use camelCase for .NET class or method names** +- ❌ **NEVER forget to dispose AWS clients (use using statements)** +- ❌ **NEVER ignore proper exception handling for AWS operations** +- ❌ **NEVER skip NuGet package management** +- ❌ **NEVER assume credentials without testing first** +- ❌ **NEVER use other language folders for patterns** + +### Best Practices +- ✅ **ALWAYS create examples in the dotnetv4 directory unless instructed otherwise** +- ✅ **ALWAYS follow the established .NET project structure** +- ✅ **ALWAYS use PascalCase for .NET identifiers** +- ✅ **ALWAYS use using statements for AWS client management** +- ✅ **ALWAYS include proper exception handling for AWS service calls** +- ✅ **ALWAYS test AWS credentials before assuming credential issues** +- ✅ **ALWAYS include comprehensive XML documentation** +- ✅ **ALWAYS use async/await patterns for AWS operations** +- ✅ **ALWAYS use dependency injection for AWS services** +- ✅ **ALWAYS create a separate class in the Actions project for the Hello example** +- ✅ **ALWAYS add project files to the main solution file DotNetV4Examples.sln** +- ✅ **ALWAYS put print statements in the action methods if possible** + +### Project Configuration Requirements +- **Target Framework**: Specify appropriate .NET version in .csproj +- **AWS SDK packages**: Include specific AWS service NuGet packages +- **Test packages**: Include xUnit and test runner packages +- **Configuration**: Support for appsettings.json and environment variables + +### Integration with Knowledge Base +Before creating .NET code examples: +1. Query `coding-standards-KB` for "DotNet-code-example-standards" +2. Query `DotNet-premium-KB` for "DotNet implementation patterns" +3. Follow KB-documented patterns for project structure and class organization +4. Validate against existing .NET examples only after KB consultation \ No newline at end of file diff --git a/steering_docs/dotnet-tech/basics.md b/steering_docs/dotnet-tech/basics.md new file mode 100644 index 00000000000..98a94e968bc --- /dev/null +++ b/steering_docs/dotnet-tech/basics.md @@ -0,0 +1,395 @@ +# .NET Interactive Scenario Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "DotNet-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("DotNet-premium-KB", ".NET implementation patterns structure") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate interactive scenarios that demonstrate complete workflows using multiple service operations in a guided, educational manner. Implementation must be based on the service SPECIFICATION.md file. + +## Requirements +- **Specification-Driven**: MUST read the `scenarios/basics/{service}/SPECIFICATION.md` +- **Interactive**: Use Console.WriteLine and Console.ReadLine for user input and guidance +- **Educational**: Break complex workflows into logical phases +- **Comprehensive**: Cover setup, demonstration, examination, and cleanup +- **Error Handling**: Graceful error handling with user-friendly messages +- **Wrapper Classes**: MUST use service wrapper classes for all operations +- **Namespaces**: MUST use file-level namespaces that match the project names +- **Using Statements**: MUST cleanup unused using statements + +## File Structure +``` +dotnetv4/{Service}/Scenarios/{Service}_Basics/ +├── {Service}Basics.cs # Main scenario file +├── {Service}Basics.csproj # Project file +``` + +## MANDATORY Pre-Implementation Steps + +### Step 1: Read Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first to understand: +- **API Actions Used**: Exact operations to implement +- **Proposed Example Structure**: Setup, demonstration, examination, cleanup phases +- **Error Handling**: Specific error codes and handling requirements +- **Scenario Flow**: Step-by-step workflow description + +### Step 2: Extract Implementation Requirements +From the specification, identify: +- **Setup Phase**: What resources need to be created/configured +- **Demonstration Phase**: What operations to demonstrate +- **Examination Phase**: What data to display and how to filter/analyze +- **Cleanup Phase**: What resources to clean up and user options + +## Scenario Class Pattern +### Implementation Pattern Based on SPECIFICATION.md +```csharp +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// +/// Purpose +/// +/// Shows how to use {AWS Service} to {scenario description}. This scenario demonstrates: +/// +/// 1. {Phase 1 description} +/// 2. {Phase 2 description} +/// 3. {Phase 3 description} +/// 4. {Phase 4 description} +/// +/// This example uses the AWS SDK for .NET v4 to interact with {AWS Service}. +/// + +using System; +using System.Threading.Tasks; +using Amazon.{Service}; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Amazon.DocSamples.{Service} +{ + public class {Service}Basics + { + private static ILogger logger = null!; + private static {Service}Wrapper wrapper = null!; + private static string? resourceId = null; + + /// + /// Main entry point for the {AWS Service} basics scenario. + /// + /// Command line arguments. + public static async Task Main(string[] args) + { + using var host = Host.CreateDefaultBuilder(args) + .ConfigureServices((_, services) => + services.AddAWSService() + .AddTransient<{Service}Wrapper>() + ) + .Build(); + + logger = LoggerFactory.Create(builder => { builder.AddConsole(); }) + .CreateLogger<{Service}Basics>(); + + wrapper = host.Services.GetRequiredService<{Service}Wrapper>(); + + await RunScenario(); + } + + /// + /// Runs the {AWS Service} basics scenario. + /// + public static async Task RunScenario() + { + Console.WriteLine(new string('-', 88)); + Console.WriteLine("Welcome to the {AWS Service} basics scenario!"); + Console.WriteLine(new string('-', 88)); + Console.WriteLine("{Service description and what users will learn}"); + Console.WriteLine(); + + try + { + await SetupPhase(); + await DemonstrationPhase(); + await ExaminationPhase(); + } + catch (Exception ex) + { + logger.LogError("Scenario failed: {Message}", ex.Message); + Console.WriteLine($"The scenario encountered an error: {ex.Message}"); + } + finally + { + await CleanupPhase(); + } + } + + /// + /// Setup phase: Implement based on specification's Setup section. + /// + private static async Task SetupPhase() + { + Console.WriteLine("Setting up {AWS Service}..."); + Console.WriteLine(); + + // Example: Check for existing resources (from specification) + var existingResources = await wrapper.ListResourcesAsync(); + if (existingResources.Count > 0) + { + Console.WriteLine($"Found {existingResources.Count} existing resource(s):"); + foreach (var resource in existingResources) + { + Console.WriteLine($" - {resource}"); + } + + Console.Write("Would you like to use an existing resource? (y/n): "); + var useExisting = Console.ReadLine()?.ToLower() == "y"; + if (useExisting) + { + resourceId = existingResources[0]; + return; + } + } + } + + /// + /// Demonstration phase: Implement operations from specification. + /// + private static async Task DemonstrationPhase() + { + Console.WriteLine("Demonstrating {AWS Service} capabilities..."); + Console.WriteLine(); + + // Implement specific operations from specification + // Example: Generate sample data if specified + await wrapper.CreateSampleDataAsync(resourceId); + Console.WriteLine("✓ Sample data created successfully"); + + // Wait if specified in the specification + Console.WriteLine("Waiting for data to be processed..."); + await Task.Delay(5000); + } + + /// + /// Examination phase: Implement data analysis from specification. + /// + private static async Task ExaminationPhase() + { + Console.WriteLine("Examining {AWS Service} data..."); + Console.WriteLine(); + + // List and examine data as specified + var dataItems = await wrapper.ListDataAsync(resourceId); + if (dataItems.Count == 0) + { + Console.WriteLine("No data found. Data may take a few minutes to appear."); + return; + } + + Console.WriteLine($"Found {dataItems.Count} data item(s)"); + + // Get detailed information as specified + var detailedData = await wrapper.GetDataDetailsAsync(resourceId, dataItems.Take(5).ToList()); + DisplayDataSummary(detailedData); + + // Show detailed view if specified + if (detailedData.Count > 0) + { + Console.Write("Would you like to see detailed information? (y/n): "); + var showDetails = Console.ReadLine()?.ToLower() == "y"; + if (showDetails) + { + DisplayDataDetails(detailedData[0]); + } + } + + // Filter data as specified + FilterDataByCriteria(dataItems); + } + + /// + /// Cleanup phase: Implement cleanup options from specification. + /// + private static async Task CleanupPhase() + { + if (string.IsNullOrEmpty(resourceId)) + return; + + Console.WriteLine("Cleanup options:"); + Console.WriteLine("Note: Deleting the resource will stop all monitoring/processing."); + + Console.Write("Would you like to delete the resource? (y/n): "); + var deleteResource = Console.ReadLine()?.ToLower() == "y"; + + if (deleteResource) + { + try + { + await wrapper.DeleteResourceAsync(resourceId); + Console.WriteLine($"✓ Deleted resource: {resourceId}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error deleting resource: {ex.Message}"); + } + } + else + { + Console.WriteLine($"Resource {resourceId} will continue running."); + Console.WriteLine("You can manage it through the AWS Console or delete it later."); + } + } + } +} +``` + +## Scenario Phase Structure (Based on Specification) + +### Setup Phase +- **Read specification Setup section** for exact requirements +- Check for existing resources as specified +- Create necessary resources using wrapper methods +- Configure service settings per specification +- Verify setup completion as described + +### Demonstration Phase +- **Follow specification Demonstration section** exactly +- Perform core service operations using wrapper methods +- Generate sample data if specified in the specification +- Show service capabilities as outlined +- Provide educational context from specification + +### Examination Phase +- **Implement specification Examination section** requirements +- List and examine results using wrapper methods +- Filter and analyze data as specified +- Display detailed information per specification format +- Allow user interaction as described in specification + +### Cleanup Phase +- **Follow specification Cleanup section** guidance +- Offer cleanup options with warnings from specification +- Handle cleanup errors gracefully using wrapper methods +- Provide alternative management options as specified +- Confirm completion per specification + +## User Interaction Patterns + +### Question Types +```python +# Yes/No questions +use_existing = q.ask("Use existing resource? (y/n): ", q.is_yesno) + +# Text input +resource_name = q.ask("Enter resource name: ") + +# Numeric input +count = q.ask("How many items? ", q.is_int) +``` + +### Information Display +```python +# Progress indicators +print("✓ Operation completed successfully") +print("⚠ Warning message") +print("✗ Error occurred") + +# Formatted output +print("-" * 60) +print(f"Found {len(items)} items:") +for item in items: + print(f" • {item['name']}") +``` + +## Specification-Based Error Handling + +### Error Handling from Specification +The specification includes an "Errors" section with specific error codes and handling: + +```csharp +// Example error handling based on specification +try +{ + var response = await wrapper.CreateResourceAsync(); + return response; +} +catch (Amazon{Service}Exception ex) +{ + var errorCode = ex.ErrorCode; + if (errorCode == "BadRequestException") + { + // Handle as specified: "Validate input parameters and notify user" + Console.WriteLine("Invalid configuration. Please check your parameters."); + } + else if (errorCode == "InternalServerErrorException") + { + // Handle as specified: "Retry operation with exponential backoff" + Console.WriteLine("Service temporarily unavailable. Retrying..."); + // Implement retry logic + } + else + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + throw; +} +``` + +## Scenario Requirements +- ✅ **ALWAYS** read and implement based on `scenarios/basics/{service}/SPECIFICATION.md` +- ✅ **ALWAYS** include descriptive XML documentation at top explaining scenario steps from specification +- ✅ **ALWAYS** use Console.WriteLine and Console.ReadLine for user interaction +- ✅ **ALWAYS** use service wrapper classes for all AWS operations +- ✅ **ALWAYS** implement proper cleanup in finally block +- ✅ **ALWAYS** break scenario into logical phases per specification +- ✅ **ALWAYS** include error handling per specification's Errors section +- ✅ **ALWAYS** provide educational context and explanations from specification +- ✅ **ALWAYS** handle edge cases (no resources found, etc.) as specified + +## Implementation Workflow + +### Step-by-Step Implementation Process +1. **Read Specification**: Study `scenarios/basics/{service}/SPECIFICATION.md` thoroughly +2. **Extract API Actions**: Note all API actions listed in "API Actions Used" section +3. **Map to Wrapper Methods**: Ensure wrapper class has methods for all required actions +4. **Implement Phases**: Follow the "Proposed example structure" section exactly +5. **Add Error Handling**: Implement error handling per the "Errors" section +6. **Test Against Specification**: Verify implementation matches specification requirements + +### Specification Sections to Implement +- **API Actions Used**: All operations must be available in wrapper class +- **Proposed example structure**: Direct mapping to scenario phases +- **Setup**: Exact setup steps and resource creation +- **Demonstration**: Specific operations to demonstrate +- **Examination**: Data analysis and filtering requirements +- **Cleanup**: Resource cleanup options and user choices +- **Errors**: Specific error codes and handling strategies + +## Error Handling in Scenarios +- **Follow specification error table**: Implement exact error handling per specification +- Catch and display user-friendly error messages per specification guidance +- Continue scenario execution when possible as specified +- Provide guidance on resolving issues from specification +- Ensure cleanup runs even if errors occur + +## Educational Elements +- **Use specification descriptions**: Explain operations using specification language +- Show before/after states as outlined in specification +- Provide context about service capabilities from specification +- Include tips and best practices mentioned in specification +- Follow the educational flow described in specification structure \ No newline at end of file diff --git a/steering_docs/dotnet-tech/hello.md b/steering_docs/dotnet-tech/hello.md new file mode 100644 index 00000000000..2d50ef4a0c8 --- /dev/null +++ b/steering_docs/dotnet-tech/hello.md @@ -0,0 +1,126 @@ +# .NET Hello Examples Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "DotNet-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("DotNet-premium-KB", ".NET implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate simple "Hello" examples that demonstrate basic service connectivity and the most fundamental operation using direct AWS SDK for .NET client calls. + +## Requirements +- **MANDATORY**: Every AWS service MUST include a "Hello" scenario +- **Simplicity**: Should be the most basic, minimal example possible +- **Standalone**: Must work independently of other examples +- **Direct Client**: Use AWS SDK for .NET client directly, no wrapper classes needed + +## File Structure +``` +dotnetv4/{Service}/Actions/ +├── Hello{Service}.cs # Hello example file +``` + +## Hello Example Pattern +```csharp +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// +/// Purpose +/// +/// Shows how to get started with {AWS Service} by {basic operation description}. +/// + +using System; +using System.Threading.Tasks; +using Amazon.{Service}; +using Amazon.{Service}.Model; + +namespace Amazon.DocSamples.{Service} +{ + public class Hello{Service} + { + /// + /// Use the AWS SDK for .NET to create an {AWS Service} client and + /// {basic operation description}. + /// This example uses the default settings specified in your shared credentials + /// and config files. + /// + /// Command line arguments. + public static async Task Main(string[] args) + { + try + { + // Create service client + using var {service}Client = new Amazon{Service}Client(); + + // Perform the most basic operation for this service + var response = await {service}Client.{BasicOperation}Async(); + + Console.WriteLine("Hello, {AWS Service}!"); + // Display appropriate result information + + } + catch (Amazon{Service}Exception ex) + { + if (ex.ErrorCode == "UnauthorizedOperation") + { + Console.WriteLine("You don't have permission to access {AWS Service}."); + } + else + { + Console.WriteLine($"Couldn't access {AWS Service}. Error: {ex.Message}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"An unexpected error occurred: {ex.Message}"); + } + } + } +} +``` + +## Hello Examples by Service Type + +### List-Based Services (S3, DynamoDB, etc.) +- **Operation**: List primary resources (buckets, tables, etc.) +- **Message**: Show count and names of resources + +### Status-Based Services (GuardDuty, Config, etc.) +- **Operation**: Check service status or list detectors/configurations +- **Message**: Show service availability and basic status + +### Compute Services (EC2, Lambda, etc.) +- **Operation**: List instances/functions or describe regions +- **Message**: Show available resources or regions + +## Validation Requirements +- ✅ **Must run without errors** (with proper credentials) +- ✅ **Must handle credential issues gracefully** +- ✅ **Must display meaningful output** +- ✅ **Must use direct AWS SDK for .NET client calls** +- ✅ **Must include proper XML documentation** + +## Common Patterns +- Always use `new Amazon{Service}Client()` directly +- Include comprehensive error handling with try-catch blocks +- Provide user-friendly output messages using Console.WriteLine +- Handle both service-specific and general exceptions +- Keep it as simple as possible - no additional classes or complexity +- Use async/await pattern for all AWS operations \ No newline at end of file diff --git a/steering_docs/dotnet-tech/metadata.md b/steering_docs/dotnet-tech/metadata.md new file mode 100644 index 00000000000..8bb2f4fa5de --- /dev/null +++ b/steering_docs/dotnet-tech/metadata.md @@ -0,0 +1,215 @@ +# .NET Metadata Generation + +## Purpose +Generate documentation metadata files that integrate with AWS Documentation pipeline for snippet extraction and cross-referencing. + +## Requirements +- **Specification First**: Always check service specification for exact metadata keys +- **Snippet Tags**: Match snippet tags in code exactly +- **Complete Coverage**: Include all actions and scenarios from specification + +## File Structure +``` +.doc_gen/metadata/ +├── {service}_metadata.yaml # Service metadata file +``` + +## Metadata Discovery Process + +### Step 1: Check Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first for metadata requirements. + +Look for the metadata table: +```markdown +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`CreateDetector` |{service}_metadata.yaml |{service}_CreateDetector | +|`GetDetector` |{service}_metadata.yaml |{service}_GetDetector | +|`Service Basics Scenario` |{service}_metadata.yaml |{service}_Scenario | +``` + +### Step 2: Use Exact Metadata Keys +**NEVER** create custom metadata keys when specification defines them. Use the exact keys from the specification table. + +## Metadata File Pattern +```yaml +# .doc_gen/metadata/{service}_metadata.yaml + +{service}_CreateResource: + title: Create a &{ServiceAbbrev}; resource + title_abbrev: Create a resource + synopsis: create a &{ServiceAbbrev}; resource. + category: Actions + languages: + .NET: + versions: + - sdk_version: 4 + github: dotnetv4/{Service} + excerpts: + - description: + snippet_tags: + - dotnetv4.example_code.{service}.CreateResource + services: + {service}: {CreateResource} + +{service}_GetResource: + title: Get a &{ServiceAbbrev}; resource + title_abbrev: Get a resource + synopsis: get a &{ServiceAbbrev}; resource. + category: Actions + languages: + .NET: + versions: + - sdk_version: 4 + github: dotnetv4/{Service} + excerpts: + - description: + snippet_tags: + - dotnetv4.example_code.{service}.GetResource + services: + {service}: {GetResource} + +{service}_Scenario: + title: Get started with &{ServiceAbbrev}; resources + title_abbrev: Get started with resources + synopsis: learn the basics of &{ServiceAbbrev}; by creating resources and managing them. + category: Scenarios + languages: + .NET: + versions: + - sdk_version: 4 + github: dotnetv4/{Service} + excerpts: + - description: Create a {Service} wrapper class to manage operations. + snippet_tags: + - dotnetv4.example_code.{service}.{Service}Wrapper + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - dotnetv4.example_code.{service}.{Service}Scenario + services: + {service}: {CreateResource, GetResource, ListResources, DeleteResource} + +{service}_Hello: + title: Hello &{ServiceAbbrev}; + title_abbrev: Hello &{ServiceAbbrev}; + synopsis: get started using &{ServiceAbbrev};. + category: Hello + languages: + .NET: + versions: + - sdk_version: 4 + github: dotnetv4/{Service} + excerpts: + - description: + snippet_tags: + - dotnetv4.example_code.{service}.Hello + services: + {service}: {ListResources} +``` + +## Snippet Tag Requirements + +### Code Snippet Tags +All code must include proper snippet tags that match metadata: + +```csharp +// snippet-start:[dotnetv4.example_code.{service}.{ActionName}] +public async Task ActionMethodAsync() +{ + // Action implementation +} +// snippet-end:[dotnetv4.example_code.{service}.{ActionName}] +``` + +### Wrapper Class Tags +```csharp +// snippet-start:[dotnetv4.example_code.{service}.{Service}Wrapper] +public class {Service}Wrapper +{ + // Wrapper class implementation +} +// snippet-end:[dotnetv4.example_code.{service}.{Service}Wrapper] +``` + +### Scenario Tags +```csharp +// snippet-start:[dotnetv4.example_code.{service}.{Service}Scenario] +public class {Service}Basics +{ + // Scenario class implementation +} +// snippet-end:[dotnetv4.example_code.{service}.{Service}Scenario] +``` + +### Hello Tags +```csharp +// snippet-start:[dotnetv4.example_code.{service}.Hello] +public static async Task Main(string[] args) +{ + // Hello implementation +} +// snippet-end:[dotnetv4.example_code.{service}.Hello] +``` + +## Service Abbreviations + +Common service abbreviations for metadata: +- **GuardDuty**: GD +- **DynamoDB**: DDB +- **Simple Storage Service**: S3 +- **Elastic Compute Cloud**: EC2 +- **Identity and Access Management**: IAM +- **Key Management Service**: KMS +- **Simple Notification Service**: SNS +- **Simple Queue Service**: SQS + +## Metadata Categories + +### Actions +Individual service operations (CreateResource, GetResource, etc.) + +### Scenarios +Multi-step workflows demonstrating service usage + +### Hello +Simple introduction examples + +### Cross-service +Examples spanning multiple AWS services + +## Metadata Validation + +### Required Fields +- ✅ **title**: Descriptive title with service abbreviation +- ✅ **title_abbrev**: Shortened title +- ✅ **synopsis**: Brief description of what the example does +- ✅ **category**: Actions, Scenarios, Hello, or Cross-service +- ✅ **languages.Python.versions**: SDK version information +- ✅ **github**: Path to example code +- ✅ **snippet_tags**: Matching tags from code +- ✅ **services**: Service operations used + +### Validation Commands +```bash +# Validate metadata with writeme tool +cd .tools/readmes +python -m writeme --languages .NET:4 --services {service} +``` + +## Common Metadata Errors +- ❌ **Custom metadata keys** when specification exists +- ❌ **Mismatched snippet tags** between code and metadata +- ❌ **Missing service operations** in services section +- ❌ **Incorrect github paths** to example code +- ❌ **Wrong service abbreviations** in titles +- ❌ **Missing required fields** in metadata structure + +## Metadata Generation Workflow +1. **Read specification** for exact metadata requirements +2. **Extract metadata table** from specification +3. **Create metadata file** using specification keys +4. **Add snippet tags** to all code files +5. **Validate metadata** with writeme tool +6. **Fix any validation errors** before completion \ No newline at end of file diff --git a/steering_docs/dotnet-tech/orchestration.md b/steering_docs/dotnet-tech/orchestration.md new file mode 100644 index 00000000000..a747187ef1e --- /dev/null +++ b/steering_docs/dotnet-tech/orchestration.md @@ -0,0 +1,239 @@ +# .NET Code Generation Orchestration + +## Purpose +Coordinate the modular components to generate complete AWS SDK code examples. Each component can be used independently or in sequence. + +## Component Dependencies + +```mermaid +graph TD + A[Knowledge Base Consultation] --> B[Hello Example] + A --> C[Wrapper Class] + A --> D[Scenario] + + C --> E[Tests - Stubber Creation] + E --> F[Tests - Unit Tests] + E --> G[Tests - Integration Tests] + E --> H[Tests - Scenario Tests] + + B --> I[Metadata Generation] + C --> I + D --> I + + I --> J[README Generation] + + K[Service Specification] --> I + K --> C + K --> D +``` + +## Execution Workflows + +### Full Service Implementation +Complete implementation of a new AWS service: + +```bash +# 1. Knowledge Base Consultation (MANDATORY FIRST) +# Use ListKnowledgeBases + QueryKnowledgeBases for standards and patterns + +# 2. Generate Core Components +# - Hello example: Hello{Service}.cs +# - Wrapper class: {Service}Wrapper.cs +# - Scenario: {Service}Basics.cs +# - Project files: *.csproj files + +# 3. Generate Test Suite +# - Unit tests: {Service}Tests.cs +# - Integration tests: {Service}IntegrationTests.cs + +# 4. Generate Metadata +# - Read service specification for exact metadata keys +# - Create .doc_gen/metadata/{service}_metadata.yaml + +# 5. Generate Documentation +# - Run writeme tool to create/update README.md + +# 6. Build and Validate +# - Build solution with dotnet build +# - Run tests with dotnet test +``` + +### Individual Component Updates + +#### Update Hello Example Only +```bash +# Focus: hello.md guidance +# Files: {service}_hello.py +# Validation: Run hello example, check output +``` + +#### Update Wrapper Class Only +```bash +# Focus: wrapper.md guidance +# Files: {service}_wrapper.py +# Validation: Run unit tests for wrapper methods +``` + +#### Update Scenario Only +```bash +# Focus: scenario.md guidance +# Files: scenario_{service}_basics.py +# Validation: Run scenario tests, check user interaction +``` + +#### Update Tests Only +```bash +# Focus: tests.md guidance +# Files: All test files in test/ directory +# Validation: Run pytest with all markers +``` + +#### Update Metadata Only +```bash +# Focus: metadata.md guidance +# Files: .doc_gen/metadata/{service}_metadata.yaml +# Validation: Run writeme tool validation +``` + +#### Update Documentation Only +```bash +# Focus: readme.md guidance +# Files: README.md (generated) +# Validation: Check README completeness and accuracy +``` + +## Quality Gates + +### Component-Level Validation +Each component has specific validation requirements: + +#### Hello Example Validation +```bash +dotnet run --project dotnetv4/{Service}/Actions/Hello{Service}.csproj +``` + +#### Wrapper Class Validation +```bash +dotnet build dotnetv4/{Service}/Actions/{Service}Wrapper.csproj +``` + +#### Scenario Validation +```bash +dotnet run --project dotnetv4/{Service}/Scenarios/{Service}_Basics/{Service}Basics.csproj +``` + +#### Test Validation +```bash +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter Category=Integration +``` + +#### Code Quality Validation +```bash +dotnet format dotnetv4/{Service}/ +``` + +#### Documentation Validation +```bash +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages .NET:4 --services {service} +``` + +### Integration Validation +Full integration testing across all components: + +```bash +# 1. All unit tests pass +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter "Category!=Integration" + +# 2. All integration tests pass +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter Category=Integration + +# 3. All examples execute successfully +dotnet run --project dotnetv4/{Service}/Actions/Hello{Service}.csproj +dotnet run --project dotnetv4/{Service}/Scenarios/{Service}_Basics/{Service}Basics.csproj + +# 4. Code quality passes +dotnet format dotnetv4/{Service}/ + +# 5. Documentation generates successfully +cd .tools/readmes && source .venv/bin/activate && python -m writeme --languages .NET:4 --services {service} +``` + +## Component Selection Guide + +### When to Use Individual Components + +#### Hello Example Only +- Quick service introduction needed +- Testing basic service connectivity +- Creating minimal working example + +#### Wrapper Class Only +- Need reusable service operations +- Building foundation for other examples +- Focusing on error handling patterns + +#### Scenario Only +- Demonstrating complete workflows +- Educational/tutorial content +- Interactive user experiences + +#### Tests Only +- Improving test coverage +- Adding new test cases +- Fixing test infrastructure + +#### Metadata Only +- Documentation pipeline integration +- Updating snippet references +- Fixing metadata validation errors + +#### Documentation Only +- README updates needed +- Documentation refresh +- Link validation and updates + +### When to Use Full Workflow +- New service implementation +- Complete service overhaul +- Major structural changes +- Initial service setup + +## Error Recovery + +### Component Failure Handling +If any component fails, you can: + +1. **Fix and retry** the specific component +2. **Skip and continue** with other components +3. **Rollback changes** and restart from known good state + +### Common Recovery Scenarios + +#### Test Failures +```bash +# Fix test issues and re-run +python -m pytest python/example_code/{service}/test/ -v --tb=short +``` + +#### Metadata Validation Failures +```bash +# Check metadata syntax +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Validate against specification +# Compare with scenarios/basics/{service}/SPECIFICATION.md +``` + +#### Documentation Generation Failures +```bash +# Check for missing dependencies +cd .tools/readmes && source .venv/bin/activate && pip list + +# Validate metadata first +python -m writeme --languages Python:3 --services {service} --verbose +``` + +This modular approach allows for targeted updates, easier debugging, and more maintainable code generation processes. \ No newline at end of file diff --git a/steering_docs/dotnet-tech/readme_writeme.md b/steering_docs/dotnet-tech/readme_writeme.md new file mode 100644 index 00000000000..f45cbd93ca6 --- /dev/null +++ b/steering_docs/dotnet-tech/readme_writeme.md @@ -0,0 +1,227 @@ +# .NET README/WRITEME and Documentation Generation + +## Purpose +Generate and update README files and documentation using the writeme tool to ensure consistency and completeness. + +## Requirements +- **Automated Generation**: Use writeme tool for README generation +- **Metadata Dependency**: Requires complete metadata files +- **Virtual Environment**: Run writeme in isolated environment +- **Validation**: Ensure all documentation is up-to-date + +## File Structure +``` +dotnetv4/{Service}/ +├── README.md # Generated service README +├── *.csproj # Project files with dependencies +└── {service}_metadata.yaml # Metadata (in .doc_gen/metadata/) +``` + +## README Generation Process + +### Step 1: Setup Writeme Environment +```bash +cd .tools/readmes + +# Create virtual environment +python -m venv .venv + +# Activate environment (Linux/macOS) +source .venv/bin/activate + +# Activate environment (Windows) +.venv\Scripts\activate + +# Install dependencies +python -m pip install -r requirements_freeze.txt +``` + +### Step 2: Generate README +```bash +# Generate README for specific service +python -m writeme --languages .NET:4 --services {service} +``` + +### Step 3: Validate Generation +- ✅ **README.md created/updated** in service directory +- ✅ **No generation errors** in writeme output +- ✅ **All examples listed** in README +- ✅ **Proper formatting** and structure +- ✅ **Working links** to code files + +## README Content Structure + +### Generated README Sections +1. **Service Overview**: Description of AWS service +2. **Code Examples**: List of available examples +3. **Prerequisites**: Setup requirements +4. **Installation**: Dependency installation +5. **Usage**: How to run examples +6. **Tests**: Testing instructions +7. **Additional Resources**: Links to documentation + +### Example README Content +```markdown +# {AWS Service} code examples for the SDK for .NET + +## Overview + +This is a workspace where you can find the following AWS SDK for .NET v4 +{AWS Service} examples. + +## ⚠ Important + +* Running this code might result in charges to your AWS account. +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. + +## Code examples + +### Actions + +The following examples show you how to perform actions using the AWS SDK for .NET. + +* [Create a resource](Actions/{Service}Wrapper.cs#L123) (`CreateResource`) +* [Get a resource](Actions/{Service}Wrapper.cs#L456) (`GetResource`) + +### Scenarios + +The following examples show you how to implement common scenarios. + +* [Get started with resources](Scenarios/{Service}_Basics/{Service}Basics.cs) - Learn the basics by creating and managing resources. + +### Hello + +* [Hello {Service}](Actions/Hello{Service}.cs) - Get started with {AWS Service}. + +## Prerequisites + +- You must have an AWS account, and have your default credentials and AWS Region configured. +- .NET 8 or later +- AWS SDK for .NET v4 + +## Install + +Install the prerequisites using the .NET CLI: + +``` +dotnet restore +``` + +## Run the examples + +### Instructions + +All examples can be run individually. For example: + +``` +dotnet run --project Actions/Hello{Service}.csproj +``` + +### Hello {Service} + +This example shows you how to get started using {AWS Service}. + +``` +dotnet run --project Actions/Hello{Service}.csproj +``` + +### Get started with {Service} resources + +This interactive scenario runs at a command prompt and shows you how to use {AWS Service} to do the following: + +1. Create a resource +2. Use the resource +3. Clean up resources + +``` +dotnet run --project Scenarios/{Service}_Basics/{Service}Basics.csproj +``` + +## Run the tests + +Unit tests in this module use xUnit. To run all of the tests, +run the following in your [GitHub root]/dotnetv4/{Service} folder. + +``` +dotnet test +``` + +## Additional resources + +- [{AWS Service} User Guide](https://docs.aws.amazon.com/{service}/latest/ug/) +- [{AWS Service} API Reference](https://docs.aws.amazon.com/{service}/latest/APIReference/) +- [AWS SDK for .NET ({AWS Service})](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/{Service}/{Service}NET.html) +``` + +## Documentation Dependencies + +### Required Files for README Generation +- ✅ **Metadata file**: `.doc_gen/metadata/{service}_metadata.yaml` +- ✅ **Code files**: All referenced .NET files must exist +- ✅ **Snippet tags**: All snippet tags in metadata must exist in code +- ✅ **Project files**: `*.csproj` files with dependencies + +### Metadata Integration +The writeme tool uses metadata to: +- Generate example lists and descriptions +- Create links to specific code sections +- Include proper service information +- Format documentation consistently + +## Troubleshooting README Generation + +### Common Issues +- **Missing metadata**: Ensure metadata file exists and is valid +- **Broken snippet tags**: Verify all snippet tags exist in code +- **File not found**: Check all file paths in metadata +- **Invalid YAML**: Validate metadata YAML syntax + +### Error Resolution +```bash +# Check for metadata errors +python -m writeme --languages .NET:4 --services {service} --verbose + +# Validate specific metadata file +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Check for missing snippet tags +grep -r "snippet-start" dotnetv4/{Service}/ +``` + +## README Maintenance + +### When to Regenerate README +- ✅ **After adding new examples** +- ✅ **After updating metadata** +- ✅ **After changing code structure** +- ✅ **Before committing changes** +- ✅ **During regular maintenance** + +### README Quality Checklist +- ✅ **All examples listed** and properly linked +- ✅ **Prerequisites accurate** and complete +- ✅ **Installation instructions** work correctly +- ✅ **Usage examples** are clear and correct +- ✅ **Links functional** and point to right locations +- ✅ **Formatting consistent** with other services + +## Integration with CI/CD + +### Automated README Validation +```bash +# In CI/CD pipeline, validate README is up-to-date +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages .NET:4 --services {service} --check + +# Exit with error if README needs updates +if git diff --exit-code dotnetv4/{Service}/README.md; then + echo "README is up-to-date" +else + echo "README needs to be regenerated" + exit 1 +fi +``` + +This ensures documentation stays synchronized with code changes. \ No newline at end of file diff --git a/steering_docs/dotnet-tech/tests.md b/steering_docs/dotnet-tech/tests.md new file mode 100644 index 00000000000..6576e7ba8c9 --- /dev/null +++ b/steering_docs/dotnet-tech/tests.md @@ -0,0 +1,320 @@ +# .NET Test Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "dotnet-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("DotNet-premium-KB", ".NET implementation patterns testing") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate comprehensive test suites including unit tests and integration tests using xUnit framework with proper mocking and AWS data structures. + +## Requirements +- **Complete Data**: Use complete AWS data structures in tests +- **Proper Attributes**: Use xUnit attributes for test categorization +- **Error Coverage**: Test all error conditions from specification +- **Async Testing**: Use async Task for async test methods + +## File Structure +``` +dotnetv4/{Service}/Tests/ +├── {Service}Tests.csproj # Test project file +├── {Service}Tests.cs # Unit and integration tests +``` + +## Test Project Setup + +### Step 1: Create Test Project File +```xml + + + + + net8.0 + enable + enable + false + true + + + + + + + + + + + + + + + + + +``` + +### Step 2: Create Test Class Structure +```csharp +// dotnetv4/{Service}/Tests/{Service}Tests.cs +using System; +using System.Threading.Tasks; +using Amazon.{Service}; +using Amazon.{Service}.Model; +using Moq; +using Xunit; +using Xunit.Abstractions; + +namespace Amazon.DocSamples.{Service}.Tests +{ + public class {Service}Tests + { + private readonly ITestOutputHelper _output; + private readonly Mock _mock{Service}Client; + private readonly {Service}Wrapper _wrapper; + + public {Service}Tests(ITestOutputHelper output) + { + _output = output; + _mock{Service}Client = new Mock(); + _wrapper = new {Service}Wrapper(_mock{Service}Client.Object); + } + } +} +``` + +## Unit Test Pattern +```csharp +[Theory] +[InlineData(null)] +[InlineData("BadRequestException")] +[InlineData("InternalServerErrorException")] +public async Task Test{ActionName}Async_WithVariousConditions_ReturnsExpectedResult(string? errorCode) +{ + // Arrange + var paramValue = "test-value"; + var expectedResponse = new {ActionName}Response + { + ResponseKey = "response-value" + }; + + if (errorCode == null) + { + _mock{Service}Client + .Setup(x => x.{ActionName}Async(It.IsAny<{ActionName}Request>(), default)) + .ReturnsAsync(expectedResponse); + } + else + { + _mock{Service}Client + .Setup(x => x.{ActionName}Async(It.IsAny<{ActionName}Request>(), default)) + .ThrowsAsync(new Amazon{Service}Exception(errorCode)); + } + + // Act & Assert + if (errorCode == null) + { + var result = await _wrapper.{ActionName}Async(paramValue); + Assert.Equal("response-value", result.ResponseKey); + } + else + { + var exception = await Assert.ThrowsAsync( + () => _wrapper.{ActionName}Async(paramValue)); + Assert.Equal(errorCode, exception.ErrorCode); + } +} +``` + +## Complete AWS Data Structures + +### CRITICAL: Use Complete AWS Response Data +```csharp +// ❌ WRONG - Minimal data that fails validation +var findings = new List +{ + new Finding { Id = "finding-1", Type = "SomeType", Severity = 8.0 } +}; + +// ✅ CORRECT - Complete AWS data structure +var findings = new List +{ + new Finding + { + Id = "finding-1", + AccountId = "123456789012", + Arn = "arn:aws:service:region:account:resource/id", + Type = "SomeType", + Severity = 8.0, + CreatedAt = DateTime.Parse("2023-01-01T00:00:00.000Z"), + UpdatedAt = DateTime.Parse("2023-01-01T00:00:00.000Z"), + Region = "us-east-1", + SchemaVersion = "2.0", + Resource = new Resource { ResourceType = "Instance" } + } +}; +``` + +## Integration Test Pattern +Create a single integration test for the scenario by setting IsInteractive to false: + +```csharp +using {Service}Basics; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace {Service}Tests; + +/// +/// Integration tests for the Amazon {Service} Basics scenario. +/// +public class {Service}BasicsTest +{ + /// + /// Verifies the scenario with an integration test. No errors should be logged. + /// + /// A task representing the asynchronous test operation. + [Fact] + [Trait("Category", "Integration")] + public async Task TestScenario() + { + // Arrange. + {Service}Basics.IsInteractive = false; + var loggerMock = new Mock>(); + loggerMock.Setup(logger => logger.Log( + It.Is(logLevel => logLevel == LogLevel.Error), + It.IsAny(), + It.Is((@object, @type) => true), + It.IsAny(), + It.IsAny>())); + + // Act. + await {Service}Basics.Main(new string[] { "" }); + + // Assert no exceptions or errors logged. + loggerMock.Verify(logger => logger.Log( + It.Is(logLevel => logLevel == LogLevel.Error), + It.IsAny(), + It.Is((@object, @type) => true), + It.IsAny(), + It.IsAny>()), + Times.Never); + } +} +``` + +## Additional Integration Test Patterns (Optional) +If needed, you can add specific wrapper method tests: + +```csharp +[Fact] +[Trait("Category", "Integration")] +public async Task Test{ActionName}Integration() +{ + // Arrange + var wrapper = new {Service}Wrapper(new Amazon{Service}Client()); + + // Act - This should not raise an exception + var result = await wrapper.{ActionName}Async(); + + // Assert - Verify result structure + Assert.NotNull(result); +} + +[Fact] +[Trait("Category", "Integration")] +public async Task TestResourceLifecycleIntegration() +{ + // Arrange + var wrapper = new {Service}Wrapper(new Amazon{Service}Client()); + string? resourceId = null; + + try + { + // Act - Create resource + resourceId = await wrapper.CreateResourceAsync(); + Assert.NotNull(resourceId); + + // Use resource + var result = await wrapper.GetResourceAsync(resourceId); + Assert.NotNull(result); + } + finally + { + // Clean up + if (!string.IsNullOrEmpty(resourceId)) + { + try + { + await wrapper.DeleteResourceAsync(resourceId); + } + catch + { + // Ignore cleanup errors + } + } + } +} +``` + +## Test Execution Commands + +### Unit Tests +```bash +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter "Category!=Integration" +``` + +### Integration Tests (Runs Complete Scenario) +```bash +dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter Category=Integration +``` + +## Test Requirements Checklist +- ✅ **Test project file created** with proper dependencies +- ✅ **Mock framework setup** (Moq for mocking AWS clients and loggers) +- ✅ **Complete AWS data structures** in all tests +- ✅ **Proper xUnit attributes** (`[Trait("Category", "Integration")]`) +- ✅ **Error condition coverage** per specification +- ✅ **Integration test sets IsInteractive to false** for automated testing +- ✅ **Logger verification** to ensure no errors are logged +- ✅ **Async test methods** using `async Task` + +## Integration Test Focus + +### Primary Test: Complete Scenario Integration +The main integration test should: +- ✅ **Run the entire scenario** from start to finish +- ✅ **Set IsInteractive to false** to automate the interactive parts +- ✅ **Test against real AWS** services (not mocks) +- ✅ **Verify no errors are logged** using mock logger verification +- ✅ **Handle cleanup automatically** through scenario logic + +### Test Structure Priority +1. **Integration Test** - Most important, tests complete workflow +2. **Unit Tests** - Test individual wrapper methods +3. **Additional Integration Tests** - Optional, for specific edge cases + +## Common Test Failures to Avoid +- ❌ **Not setting IsInteractive to false** in scenario integration tests +- ❌ **Using incomplete AWS data structures** in unit tests +- ❌ **Missing xUnit attributes** for integration tests +- ❌ **Not verifying logger mock** to ensure no errors are logged +- ❌ **Forgetting to set AWS region** in test clients +- ❌ **Not testing all error conditions** from specification +- ❌ **Not calling Main method properly** in scenario integration tests +- ❌ **Missing proper async/await patterns** in test methods \ No newline at end of file diff --git a/steering_docs/dotnet-tech/wrapper.md b/steering_docs/dotnet-tech/wrapper.md new file mode 100644 index 00000000000..fe858234bfe --- /dev/null +++ b/steering_docs/dotnet-tech/wrapper.md @@ -0,0 +1,293 @@ +# .NET Service Wrapper Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "dotnet-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("dotnet-premium-KB", ".NET implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate service wrapper classes that encapsulate AWS service functionality with proper error handling and logging. + +## Requirements +- **MANDATORY**: Every service MUST have a wrapper class +- **Error Handling**: Handle service-specific errors appropriately +- **Logging**: Include comprehensive logging for all operations +- **Async Methods**: Use async/await pattern for all AWS operations + +## File Structure +``` +dotnetv4/{Service}/Actions/ +├── {Service}Wrapper.cs # Service wrapper class +├── {Service}Wrapper.csproj # Project file +``` + +## Wrapper Class Pattern +```csharp +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/// +/// Purpose +/// +/// Shows how to use the AWS SDK for .NET with {AWS Service} to +/// {service description and main use cases}. +/// + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Amazon.{Service}; +using Amazon.{Service}.Model; +using Microsoft.Extensions.Logging; + +namespace Amazon.DocSamples.{Service} +{ + // snippet-start:[dotnetv4.example_code.{service}.{Service}Wrapper] + /// + /// Encapsulates {AWS Service} functionality. + /// + public class {Service}Wrapper + { + private readonly IAmazon{Service} _{service}Client; + private readonly ILogger<{Service}Wrapper> _logger; + + /// + /// Initializes a new instance of the {Service}Wrapper class. + /// + /// The {AWS Service} client. + /// The logger instance. + public {Service}Wrapper(IAmazon{Service} {service}Client, ILogger<{Service}Wrapper> logger) + { + _{service}Client = {service}Client; + _logger = logger; + } + + } + // snippet-end:[dotnetv4.example_code.{service}.{Service}Wrapper] + + // Individual action methods follow... +} +``` + +## Action Method Pattern +```csharp + // snippet-start:[dotnetv4.example_code.{service}.{ActionName}] + /// + /// {Action description}. + /// + /// Parameter description. + /// Response description. + public async Task<{ActionName}Response> {ActionMethod}Async(string param) + { + try + { + var request = new {ActionName}Request + { + Parameter = param + }; + + var response = await _{service}Client.{ActionName}Async(request); + _logger.LogInformation("{Action} completed successfully", "{ActionName}"); + return response; + } + catch (Amazon{Service}Exception ex) + { + var errorCode = ex.ErrorCode; + if (errorCode == "SpecificError") + { + _logger.LogError("Specific error handling message"); + } + else if (errorCode == "AnotherSpecificError") + { + _logger.LogError("Another specific error handling message"); + } + else + { + _logger.LogError("Error in {ActionName}: {Message}", ex.Message); + } + throw; + } + } + // snippet-end:[dotnetv4.example_code.{service}.{ActionName}] +``` + +## Paginator Pattern for List Operations +```csharp + // snippet-start:[dotnetv4.example_code.{service}.List{Resources}] + /// + /// Lists all {resources} using pagination to retrieve complete results. + /// + /// A list of all {resources}. + public async Task> List{Resources}Async() + { + try + { + var {resources} = new List<{Resource}>(); + var {resources}Paginator = _{service}Client.Paginators.List{Resources}(new List{Resources}Request()); + + await foreach (var response in {resources}Paginator.Responses) + { + {resources}.AddRange(response.{Resources}); + } + + _logger.LogInformation("Retrieved {Count} {resources}", {resources}.Count); + return {resources}; + } + catch (Amazon{Service}Exception ex) + { + var errorCode = ex.ErrorCode; + if (errorCode == "BadRequestException") + { + _logger.LogError("Invalid request parameters for listing {resources}"); + } + else + { + _logger.LogError("Error listing {resources}: {Message}", ex.Message); + } + throw; + } + } + // snippet-end:[dotnetv4.example_code.{service}.List{Resources}] +``` + +## Paginator with Parameters Pattern +```csharp + // snippet-start:[dotnetv4.example_code.{service}.List{Resources}WithFilter] + /// + /// Lists {resources} with optional filtering, using pagination. + /// + /// Optional criteria to filter results. + /// A list of filtered {resources}. + public async Task> List{Resources}WithFilterAsync(FilterCriteria? filterCriteria = null) + { + try + { + var request = new List{Resources}Request(); + if (filterCriteria != null) + { + request.FilterCriteria = filterCriteria; + } + + var {resources} = new List<{Resource}>(); + var {resources}Paginator = _{service}Client.Paginators.List{Resources}(request); + + await foreach (var response in {resources}Paginator.Responses) + { + {resources}.AddRange(response.{Resources}); + } + + _logger.LogInformation("Retrieved {Count} filtered {resources}", {resources}.Count); + return {resources}; + } + catch (Amazon{Service}Exception ex) + { + _logger.LogError("Error listing {resources} with filter: {Message}", ex.Message); + throw; + } + } + // snippet-end:[dotnetv4.example_code.{service}.List{Resources}WithFilter] +``` + +## Error Handling Requirements + +### Service-Specific Errors +Based on the service specification, handle these error types: +- **BadRequestException**: Validate input parameters +- **InternalServerErrorException**: Retry with exponential backoff +- **ResourceNotFoundException**: Handle missing resources gracefully +- **AccessDeniedException**: Provide clear permission guidance + +### Error Handling Pattern +```csharp +try +{ + var response = await _{service}Client.OperationAsync(); + return response; +} +catch (Amazon{Service}Exception ex) +{ + var errorCode = ex.ErrorCode; + if (errorCode == "BadRequestException") + { + _logger.LogError("Validate input parameters and notify user"); + } + else if (errorCode == "InternalServerErrorException") + { + _logger.LogError("Retry operation with exponential backoff"); + } + else + { + _logger.LogError("Error in operation: {Message}", ex.Message); + } + throw; +} +``` + +## Wrapper Class Requirements +- ✅ **ALWAYS** include proper logging for all operations +- ✅ **ALWAYS** provide `FromClient()` static method +- ✅ **ALWAYS** handle service-specific errors per specification +- ✅ **ALWAYS** include comprehensive XML documentation +- ✅ **ALWAYS** use async/await pattern for all AWS operations +- ✅ **ALWAYS** follow the established naming conventions +- ✅ **ALWAYS** use pagination for list operations when available +- ✅ **ALWAYS** retrieve complete results, not just first page + +## Method Naming Conventions +- Use PascalCase for method names +- Match AWS API operation names with Async suffix (e.g., `ListBucketsAsync` for `ListBuckets`) +- Use descriptive parameter names +- Return appropriate data types (Task, Task>, etc.) + +## Pagination Requirements +- **MANDATORY**: Use AWS SDK for .NET paginators for list operations when available +- **Complete Results**: Ensure all pages are retrieved, not just first page +- **Efficient**: Use built-in paginator pattern with `await foreach` + +## Pagination Usage Guidelines + +### When to Use Pagination +- ✅ **List Operations**: Always use for operations that return lists of resources +- ✅ **Large Result Sets**: Essential for services that may return many items +- ✅ **Complete Data**: Ensures all results are retrieved, not just first page + +### How to Implement Pagination +```csharp +var allItems = new List(); +var itemsPaginator = _client.Paginators.ListItems(new ListItemsRequest()); + +await foreach (var response in itemsPaginator.Responses) +{ + allItems.AddRange(response.Items); +} +``` + +### Common Paginated Operations +- `ListBuckets` → Use pagination if available +- `ListObjects` → Always use pagination (can return thousands of objects) +- `ListTables` → Use pagination for complete results +- `DescribeInstances` → Use pagination for large environments +- `ListFunctions` → Use pagination for complete function list + +## Documentation Requirements +- Include class-level XML documentation explaining service purpose +- Document all parameters with XML tags and descriptions +- Document return values with XML tags and descriptions +- Include usage examples in XML documentation where helpful +- Use proper snippet tags for documentation generation +- Document pagination behavior in list method XML documentation \ No newline at end of file diff --git a/steering_docs/java-tech.md b/steering_docs/java-tech.md new file mode 100644 index 00000000000..153ee4f6503 --- /dev/null +++ b/steering_docs/java-tech.md @@ -0,0 +1,133 @@ +# Java Technology Stack & Build System + +## Java v2 Development Environment + +### Build Tools & Dependencies +- **Build System**: Apache Maven +- **Testing Framework**: JUnit 5 +- **Build Plugin**: Apache Maven Shade Plugin +- **SDK Version**: AWS SDK for Java v2 +- **Java Version**: JDK 17 + +### Common Build Commands + +```bash +# Build and Package +mvn clean compile # Compile source code +mvn package # Build with dependencies +mvn clean package # Clean and build + +# Testing +mvn test # Run all tests +mvn test -Dtest=ClassName # Run specific test class +mvn test -Dtest=ClassName#methodName # Run specific test method + +# Execution +java -cp target/PROJECT-1.0-SNAPSHOT.jar com.example.Main +mvn exec:java -Dexec.mainClass="com.example.Main" +``` + +### Java-Specific Pattern Requirements + +#### File Naming Conventions +- Use PascalCase for class names +- Service prefix pattern: `{Service}Action.java` (e.g., `S3ListBuckets.java`) +- Hello scenarios: `Hello{Service}.java` (e.g., `HelloS3.java`) +- Test files: `{Service}ActionTest.java` + +#### Hello Scenario Structure +- **Class naming**: `Hello{Service}.java` class with main method +- **Method structure**: Static main method as entry point +- **Documentation**: Include Javadoc explaining the hello example purpose + +#### Code Structure Standards +- **Package naming**: Use reverse domain notation (e.g., `com.example.s3`) +- **Class structure**: One public class per file matching filename +- **Method naming**: Use camelCase for method names +- **Constants**: Use UPPER_SNAKE_CASE for static final variables +- **Imports**: Group imports logically (Java standard, AWS SDK, other libraries) + +#### Error Handling Patterns +```java +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.services.s3.model.S3Exception; + +public class ExampleClass { + public void exampleMethod() { + try (S3Client s3Client = S3Client.builder().build()) { //For Hello examples, use Sync service clients. For Scenario examples or working with service client, use the Java Async client. + // AWS service call + var response = s3Client.operation(); + // Process response + } catch (S3Exception e) { + // Handle service-specific exceptions + System.err.println("S3 Error: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (SdkException e) { + // Handle general SDK exceptions + System.err.println("SDK Error: " + e.getMessage()); + throw e; + } + } +} +``` + +#### Testing Standards +- **Test framework**: Use JUnit 5 annotations (`@Test`, `@BeforeEach`, `@AfterEach`) +- **Integration tests**: Mark with `@Tag("IntegrationTest")` or similar +- **Resource management**: Use Github standards for AWS clients +- **Assertions**: Use JUnit 5 assertion methods +- **Test naming**: Use descriptive method names explaining test purpose + +#### Maven Project Structure +``` +src/ +├── main/ +│ └── java/ +│ └── com/ +│ └── example/ +│ └── {service}/ +│ ├── Hello{Service}.java +│ ├── {Service}Actions.java +│ └── {Service}Scenario.java +└── test/ + └── java/ + └── com/ + └── example/ + └── {service}/ + └── {Service}Test.java +``` + +#### Documentation Requirements +- **Class Javadoc**: Include purpose, usage examples, and prerequisites +- **Method Javadoc**: Document parameters, return values, and exceptions +- **Inline comments**: Explain complex AWS service interactions +- **README sections**: Include Maven setup and execution instructions + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER assume class naming without checking existing examples** +- ❌ **NEVER use snake_case for Java class or method names** +- ❌ **NEVER forget to close AWS clients (use try-with-resources)** +- ❌ **NEVER ignore proper exception handling for AWS operations** +- ❌ **NEVER skip Maven dependency management** + +### Best Practices +- ✅ **ALWAYS follow the established Maven project structure** +- ✅ **ALWAYS use PascalCase for class names and camelCase for methods** +- ✅ **ALWAYS use try-with-resources for AWS client management** +- ✅ **ALWAYS include proper exception handling for AWS service calls** +- ✅ **ALWAYS follow Java naming conventions and package structure** +- ✅ **ALWAYS include comprehensive Javadoc documentation** + +### Maven Configuration Requirements +- **AWS SDK BOM**: Include AWS SDK Bill of Materials for version management +- **Compiler plugin**: Configure for appropriate Java version +- **Shade plugin**: For creating executable JARs with dependencies +- **Surefire plugin**: For test execution configuration + +### Integration with Knowledge Base +Before creating Java code examples: +1. Query `coding-standards-KB` for "Java-code-example-standards" +2. Query `Java-premium-KB` for "Java implementation patterns" +3. Follow KB-documented patterns for Maven structure and class organization +4. Validate against existing Java examples only after KB consultation \ No newline at end of file diff --git a/steering_docs/java-tech/actions.md b/steering_docs/java-tech/actions.md new file mode 100644 index 00000000000..5bddf2d1ac4 --- /dev/null +++ b/steering_docs/java-tech/actions.md @@ -0,0 +1,408 @@ +# Java Service Actions Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Java-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Java-premium-KB", "Java implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate service actions classes that encapsulate AWS service functionality with proper error handling and logging using AWS SDK for Java V2. + +## Requirements +- **MANDATORY**: Every service MUST have an actions class +- **Error Handling**: Handle service-specific errors appropriately +- **Logging**: Include comprehensive logging for all operations +- **Static Methods**: Use static methods for reusable operations +- **Complete Responses**: Return complete AWS response objects + +## File Structure +``` +javav2/example_code/{service}/ +├── src/main/java/com/example/{service}/ +│ └── {Service}Actions.java # Service actions class +``` + +## Actions Class Pattern +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import software.amazon.awssdk.services.{service}.{Service}Client; +import software.amazon.awssdk.services.{service}.model.*; +import software.amazon.awssdk.services.{service}.paginators.*; +import software.amazon.awssdk.core.exception.SdkException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.ArrayList; + +/** + * Before running this Java V2 code example, set up your development + * environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html + * + * This Java code example shows how to perform {AWS Service} operations. + */ + +// snippet-start:[{service}.java2.{service}_actions.main] +public class {Service}Actions { + + private static final Logger logger = LoggerFactory.getLogger({Service}Actions.class); + + // Individual action methods follow... +} +// snippet-end:[{service}.java2.{service}_actions.main] +``` + +## Action Method Pattern +```java + /** + * {Action description}. + * + * @param {service}Client the {AWS Service} client to use for the operation + * @param param parameter description + * @return the {ActionName}Response object containing the result + * @throws {Service}Exception if a service-specific error occurs + * @throws SdkException if an SDK error occurs + */ + // snippet-start:[{service}.java2.{action_name}.main] + public static {ActionName}Response {actionMethod}({Service}Client {service}Client, String param) { + try { + {ActionName}Request request = {ActionName}Request.builder() + .parameter(param) + .build(); + + {ActionName}Response response = {service}Client.{actionName}(request); + logger.info("{Action} completed successfully"); + return response; + + } catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "BadRequestException": + logger.error("Invalid request parameters for {action}: {}", e.getMessage()); + break; + case "ResourceNotFoundException": + logger.error("Resource not found for {action}: {}", e.getMessage()); + break; + case "InternalServerErrorException": + logger.error("Internal server error during {action}: {}", e.getMessage()); + break; + default: + logger.error("Unexpected error during {action}: {}", e.getMessage()); + } + throw e; + } catch (SdkException e) { + logger.error("SDK error during {action}: {}", e.getMessage()); + throw e; + } + } + // snippet-end:[{service}.java2.{action_name}.main] +``` + +## Paginator Pattern for List Operations +```java + /** + * Lists all {resources} using pagination to retrieve complete results. + * + * @param {service}Client the {AWS Service} client to use for the operation + * @return a list of all {resources} + * @throws {Service}Exception if a service-specific error occurs + * @throws SdkException if an SDK error occurs + */ + // snippet-start:[{service}.java2.list_{resources}.main] + public static List<{Resource}> list{Resources}({Service}Client {service}Client) { + try { + List<{Resource}> {resources} = new ArrayList<>(); + + // Use paginator to retrieve all results + List{Resources}Iterable listIterable = {service}Client.list{Resources}Paginator(); + + listIterable.stream() + .flatMap(response -> response.{resources}().stream()) + .forEach({resources}::add); + + logger.info("Retrieved {} {resources}", {resources}.size()); + return {resources}; + + } catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "BadRequestException": + logger.error("Invalid request parameters for listing {resources}: {}", e.getMessage()); + break; + case "AccessDeniedException": + logger.error("Access denied when listing {resources}: {}", e.getMessage()); + break; + default: + logger.error("Error listing {resources}: {}", e.getMessage()); + } + throw e; + } catch (SdkException e) { + logger.error("SDK error listing {resources}: {}", e.getMessage()); + throw e; + } + } + // snippet-end:[{service}.java2.list_{resources}.main] +``` + +## Paginator with Parameters Pattern +```java + /** + * Lists {resources} with optional filtering, using pagination. + * + * @param {service}Client the {AWS Service} client to use for the operation + * @param filterCriteria optional criteria to filter results + * @return a list of filtered {resources} + * @throws {Service}Exception if a service-specific error occurs + * @throws SdkException if an SDK error occurs + */ + // snippet-start:[{service}.java2.list_{resources}_with_filter.main] + public static List<{Resource}> list{Resources}WithFilter({Service}Client {service}Client, + {FilterCriteria} filterCriteria) { + try { + List<{Resource}> {resources} = new ArrayList<>(); + + List{Resources}Request.Builder requestBuilder = List{Resources}Request.builder(); + if (filterCriteria != null) { + requestBuilder.filterCriteria(filterCriteria); + } + + List{Resources}Iterable listIterable = {service}Client.list{Resources}Paginator(requestBuilder.build()); + + listIterable.stream() + .flatMap(response -> response.{resources}().stream()) + .forEach({resources}::add); + + logger.info("Retrieved {} filtered {resources}", {resources}.size()); + return {resources}; + + } catch ({Service}Exception e) { + logger.error("Error listing {resources} with filter: {}", e.getMessage()); + throw e; + } catch (SdkException e) { + logger.error("SDK error listing {resources} with filter: {}", e.getMessage()); + throw e; + } + } + // snippet-end:[{service}.java2.list_{resources}_with_filter.main] +``` + +## Resource Creation Pattern +```java + /** + * Creates a new {resource}. + * + * @param {service}Client the {AWS Service} client to use for the operation + * @param {resourceName} the name for the new {resource} + * @return the ID of the created {resource} + * @throws {Service}Exception if a service-specific error occurs + * @throws SdkException if an SDK error occurs + */ + // snippet-start:[{service}.java2.create_{resource}.main] + public static String create{Resource}({Service}Client {service}Client, String {resourceName}) { + try { + Create{Resource}Request request = Create{Resource}Request.builder() + .{resourceName}({resourceName}) + .build(); + + Create{Resource}Response response = {service}Client.create{Resource}(request); + String {resourceId} = response.{resourceId}(); + + logger.info("Created {resource} with ID: {}", {resourceId}); + return {resourceId}; + + } catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "BadRequestException": + logger.error("Invalid parameters for creating {resource}: {}", e.getMessage()); + break; + case "ResourceAlreadyExistsException": + logger.error("{Resource} already exists: {}", e.getMessage()); + break; + case "LimitExceededException": + logger.error("Limit exceeded when creating {resource}: {}", e.getMessage()); + break; + default: + logger.error("Error creating {resource}: {}", e.getMessage()); + } + throw e; + } catch (SdkException e) { + logger.error("SDK error creating {resource}: {}", e.getMessage()); + throw e; + } + } + // snippet-end:[{service}.java2.create_{resource}.main] +``` + +## Resource Deletion Pattern +```java + /** + * Deletes a {resource}. + * + * @param {service}Client the {AWS Service} client to use for the operation + * @param {resourceId} the ID of the {resource} to delete + * @throws {Service}Exception if a service-specific error occurs + * @throws SdkException if an SDK error occurs + */ + // snippet-start:[{service}.java2.delete_{resource}.main] + public static void delete{Resource}({Service}Client {service}Client, String {resourceId}) { + try { + Delete{Resource}Request request = Delete{Resource}Request.builder() + .{resourceId}({resourceId}) + .build(); + + {service}Client.delete{Resource}(request); + logger.info("Deleted {resource} with ID: {}", {resourceId}); + + } catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "ResourceNotFoundException": + logger.error("{Resource} not found for deletion: {}", e.getMessage()); + break; + case "BadRequestException": + logger.error("Invalid request for deleting {resource}: {}", e.getMessage()); + break; + case "ConflictException": + logger.error("Cannot delete {resource} due to conflict: {}", e.getMessage()); + break; + default: + logger.error("Error deleting {resource}: {}", e.getMessage()); + } + throw e; + } catch (SdkException e) { + logger.error("SDK error deleting {resource}: {}", e.getMessage()); + throw e; + } + } + // snippet-end:[{service}.java2.delete_{resource}.main] +``` + +## Error Handling Requirements + +### Service-Specific Errors +Based on the service specification, handle these error types: +- **BadRequestException**: Validate input parameters +- **InternalServerErrorException**: Retry with exponential backoff +- **ResourceNotFoundException**: Handle missing resources gracefully +- **AccessDeniedException**: Provide clear permission guidance + +### Error Handling Pattern +```java +try { + // AWS operation + response = {service}Client.operation(request); + return response; +} catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "BadRequestException": + logger.error("Validate input parameters and notify user"); + break; + case "InternalServerErrorException": + logger.error("Retry operation with exponential backoff"); + break; + default: + logger.error("Error in operation: {}", e.getMessage()); + } + throw e; +} catch (SdkException e) { + logger.error("SDK error in operation: {}", e.getMessage()); + throw e; +} +``` + +## Actions Class Requirements +- ✅ **ALWAYS** include proper logging for all operations +- ✅ **ALWAYS** use static methods for reusability +- ✅ **ALWAYS** handle service-specific errors per specification +- ✅ **ALWAYS** include comprehensive JavaDoc documentation +- ✅ **ALWAYS** return complete AWS response objects +- ✅ **ALWAYS** follow established naming conventions +- ✅ **ALWAYS** use paginators for list operations when available +- ✅ **ALWAYS** retrieve complete results, not just first page + +## Method Naming Conventions +- Use camelCase for method names +- Match AWS API operation names (e.g., `listBuckets` for `ListBuckets`) +- Use descriptive parameter names +- Return appropriate data types (Response objects, String IDs, Lists, etc.) + +## Pagination Requirements +- **MANDATORY**: Use paginators when available for list operations +- **Complete Results**: Ensure all pages are retrieved, not just first page +- **Efficient**: Use AWS SDK paginators instead of manual pagination + +### Paginator Usage Guidelines + +#### When to Use Paginators +- ✅ **List Operations**: Always use for operations that return lists of resources +- ✅ **Large Result Sets**: Essential for services that may return many items +- ✅ **Complete Data**: Ensures all results are retrieved, not just first page + +#### How to Use Paginators +```java +// Use paginator for complete results +List{Resources}Iterable listIterable = {service}Client.list{Resources}Paginator(); + +// Stream through all pages +List<{Resource}> allResources = listIterable.stream() + .flatMap(response -> response.{resources}().stream()) + .collect(Collectors.toList()); +``` + +## Documentation Requirements +- Include class-level JavaDoc explaining service purpose +- Document all parameters with @param tags +- Document return values with @return tags +- Document exceptions with @throws tags +- Include usage examples in JavaDoc where helpful +- Use proper snippet tags for documentation generation +- Document pagination behavior in list method JavaDoc + +## Build Dependencies +Ensure proper dependencies in `pom.xml`: + +```xml + + + software.amazon.awssdk + {service} + ${aws.java.sdk.version} + + + org.slf4j + slf4j-api + 2.0.7 + + + ch.qos.logback + logback-classic + 1.4.8 + + +``` \ No newline at end of file diff --git a/steering_docs/java-tech/basics.md b/steering_docs/java-tech/basics.md new file mode 100644 index 00000000000..14518b32ade --- /dev/null +++ b/steering_docs/java-tech/basics.md @@ -0,0 +1,429 @@ +# Java Interactive Scenario Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Java-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Java-premium-KB", "Java implementation patterns structure") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate interactive scenarios that demonstrate complete workflows using multiple service operations in a guided, educational manner. Implementation must be based on the service SPECIFICATION.md file. + +## Requirements +- **Specification-Driven**: MUST read the `scenarios/basics/{service}/SPECIFICATION.md` +- **Interactive**: USE Scanner for user input and guidance +- **Educational**: Break complex workflows into logical phases +- **Comprehensive**: Cover setup, demonstration, examination, and cleanup +- **Error Handling**: Graceful error handling with user-friendly messages +- **Actions Classes**: MUST use service actions classes for all operations + +## File Structure +``` +javav2/example_code/{service}/ +├── src/main/java/com/example/{service}/ +│ ├── {Service}Scenario.java # Main scenario file +│ └── {Service}Actions.java # Actions class (if not exists) +``` + +## MANDATORY Pre-Implementation Steps + +### Step 1: Read Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first to understand: +- **API Actions Used**: Exact operations to implement +- **Proposed Example Structure**: Setup, demonstration, examination, cleanup phases +- **Error Handling**: Specific error codes and handling requirements +- **Scenario Flow**: Step-by-step workflow description + +### Step 2: Extract Implementation Requirements +From the specification, identify: +- **Setup Phase**: What resources need to be created/configured +- **Demonstration Phase**: What operations to demonstrate +- **Examination Phase**: What data to display and how to filter/analyze +- **Cleanup Phase**: What resources to clean up and user options + +## Scenario Class Pattern +### Implementation Pattern Based on SPECIFICATION.md +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.{service}.{Service}Client; +import software.amazon.awssdk.services.{service}.model.*; +import software.amazon.awssdk.core.exception.SdkException; + +import java.util.List; +import java.util.Scanner; +import java.util.concurrent.TimeUnit; + +/** + * Before running this Java V2 code example, set up your development + * environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html + * + * This Java code example performs the following tasks: + * + * 1. {Phase 1 description} + * 2. {Phase 2 description} + * 3. {Phase 3 description} + * 4. {Phase 4 description} + */ + +// snippet-start:[{service}.java2.{service}_scenario.main] +public class {Service}Scenario { + + public static final String DASHES = new String(new char[80]).replace("\0", "-"); + private static {Service}Actions {service}Actions; + private static Scanner scanner = new Scanner(System.in); + private static String resourceId; + + public static void main(String[] args) { + final String usage = """ + Usage: + + + Where: + region - The AWS region (for example, us-east-1). + """; + + if (args.length != 1) { + System.out.println(usage); + System.exit(1); + } + + String region = args[0]; + Region awsRegion = Region.of(region); + {Service}Client {service}Client = {Service}Client.builder() + .region(awsRegion) + .build(); + + {service}Actions = new {Service}Actions(); + + System.out.println(DASHES); + System.out.println("Welcome to the {AWS Service} basics scenario!"); + System.out.println(DASHES); + System.out.println(""" + {Service description and what users will learn} + """); + + try { + runScenario({service}Client); + } catch (Exception e) { + System.err.println("Scenario failed: " + e.getMessage()); + e.printStackTrace(); + } finally { + {service}Client.close(); + } + } + + private static void runScenario({Service}Client {service}Client) throws InterruptedException { + try { + setupPhase({service}Client); + demonstrationPhase({service}Client); + examinationPhase({service}Client); + } catch (Exception e) { + System.err.println("Error during scenario execution: " + e.getMessage()); + throw e; + } finally { + cleanupPhase({service}Client); + } + } + + private static void setupPhase({Service}Client {service}Client) { + System.out.println(DASHES); + System.out.println("Setting up {AWS Service}..."); + System.out.println(DASHES); + + try { + // Example: Check for existing resources (from specification) + List<{Resource}> existingResources = {service}Actions.listResources({service}Client); + if (!existingResources.isEmpty()) { + System.out.println("Found " + existingResources.size() + " existing resource(s):"); + for ({Resource} resource : existingResources) { + System.out.println(" - " + resource.{resourceName}()); + } + + System.out.print("Would you like to use an existing resource? (y/n): "); + String useExisting = scanner.nextLine(); + if (useExisting.toLowerCase().startsWith("y")) { + resourceId = existingResources.get(0).{resourceId}(); + return; + } + } + + // Create new resource as specified + System.out.println("Creating new resource..."); + resourceId = {service}Actions.createResource({service}Client); + System.out.println("✓ Resource created successfully: " + resourceId); + + } catch (SdkException e) { + System.err.println("Error during setup: " + e.getMessage()); + throw e; + } + } + + private static void demonstrationPhase({Service}Client {service}Client) throws InterruptedException { + System.out.println(DASHES); + System.out.println("Demonstrating {AWS Service} capabilities..."); + System.out.println(DASHES); + + try { + // Implement specific operations from specification + // Example: Generate sample data if specified + {service}Actions.createSampleData({service}Client, resourceId); + System.out.println("✓ Sample data created successfully"); + + // Wait if specified in the specification + System.out.println("Waiting for data to be processed..."); + TimeUnit.SECONDS.sleep(5); + + } catch (SdkException e) { + System.err.println("Error during demonstration: " + e.getMessage()); + throw e; + } + } + + private static void examinationPhase({Service}Client {service}Client) { + System.out.println(DASHES); + System.out.println("Examining {AWS Service} data..."); + System.out.println(DASHES); + + try { + // List and examine data as specified + List<{DataItem}> dataItems = {service}Actions.listData({service}Client, resourceId); + if (dataItems.isEmpty()) { + System.out.println("No data found. Data may take a few minutes to appear."); + return; + } + + System.out.println("Found " + dataItems.size() + " data item(s)"); + + // Get detailed information as specified + List<{DetailedData}> detailedData = {service}Actions.getDataDetails({service}Client, resourceId, + dataItems.subList(0, Math.min(5, dataItems.size()))); + displayDataSummary(detailedData); + + // Show detailed view if specified + if (!detailedData.isEmpty()) { + System.out.print("Would you like to see detailed information? (y/n): "); + String showDetails = scanner.nextLine(); + if (showDetails.toLowerCase().startsWith("y")) { + displayDataDetails(detailedData.get(0)); + } + } + + // Filter data as specified + filterDataByCriteria(dataItems); + + } catch (SdkException e) { + System.err.println("Error during examination: " + e.getMessage()); + throw e; + } + } + + private static void cleanupPhase({Service}Client {service}Client) { + if (resourceId == null) { + return; + } + + System.out.println(DASHES); + System.out.println("Cleanup options:"); + System.out.println("Note: Deleting the resource will stop all monitoring/processing."); + System.out.println(DASHES); + + System.out.print("Would you like to delete the resource? (y/n): "); + String deleteResource = scanner.nextLine(); + + if (deleteResource.toLowerCase().startsWith("y")) { + try { + {service}Actions.deleteResource({service}Client, resourceId); + System.out.println("✓ Deleted resource: " + resourceId); + } catch (SdkException e) { + System.err.println("Error deleting resource: " + e.getMessage()); + } + } else { + System.out.println("Resource " + resourceId + " will continue running."); + System.out.println("You can manage it through the AWS Console or delete it later."); + } + } + + private static void displayDataSummary(List<{DetailedData}> detailedData) { + System.out.println("\nData Summary:"); + for ({DetailedData} data : detailedData) { + System.out.println(" • " + data.{summaryField}()); + } + } + + private static void displayDataDetails({DetailedData} data) { + System.out.println("\nDetailed Information:"); + System.out.println(" ID: " + data.{idField}()); + System.out.println(" Status: " + data.{statusField}()); + System.out.println(" Created: " + data.{createdField}()); + // Add more fields as specified + } + + private static void filterDataByCriteria(List<{DataItem}> dataItems) { + System.out.println("\nFiltering data by criteria..."); + // Implement filtering logic as specified in the specification + } +} +// snippet-end:[{service}.java2.{service}_scenario.main] +``` + +## Scenario Phase Structure (Based on Specification) + +### Setup Phase +- **Read specification Setup section** for exact requirements +- Check for existing resources as specified +- Create necessary resources using actions methods +- Configure service settings per specification +- Verify setup completion as described + +### Demonstration Phase +- **Follow specification Demonstration section** exactly +- Perform core service operations using actions methods +- Generate sample data if specified in the specification +- Show service capabilities as outlined +- Provide educational context from specification + +### Examination Phase +- **Implement specification Examination section** requirements +- List and examine results using actions methods +- Filter and analyze data as specified +- Display detailed information per specification format +- Allow user interaction as described in specification + +### Cleanup Phase +- **Follow specification Cleanup section** guidance +- Offer cleanup options with warnings from specification +- Handle cleanup errors gracefully using actions methods +- Provide alternative management options as specified +- Confirm completion per specification + +## User Interaction Patterns + +### Input Types +```java +// Yes/No questions +System.out.print("Use existing resource? (y/n): "); +String useExisting = scanner.nextLine(); +boolean shouldUse = useExisting.toLowerCase().startsWith("y"); + +// Text input +System.out.print("Enter resource name: "); +String resourceName = scanner.nextLine(); + +// Numeric input +System.out.print("How many items? "); +int count = Integer.parseInt(scanner.nextLine()); +``` + +### Information Display +```java +// Progress indicators +System.out.println("✓ Operation completed successfully"); +System.out.println("⚠ Warning message"); +System.out.println("✗ Error occurred"); + +// Formatted output +System.out.println(DASHES); +System.out.println("Found " + items.size() + " items:"); +for (Item item : items) { + System.out.println(" • " + item.name()); +} +``` + +## Specification-Based Error Handling + +### Error Handling from Specification +The specification includes an "Errors" section with specific error codes and handling: + +```java +// Example error handling based on specification +try { + {Resource} response = {service}Actions.createResource({service}Client); + return response; +} catch ({Service}Exception e) { + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "BadRequestException": + // Handle as specified: "Validate input parameters and notify user" + System.err.println("Invalid configuration. Please check your parameters."); + break; + case "InternalServerErrorException": + // Handle as specified: "Retry operation with exponential backoff" + System.err.println("Service temporarily unavailable. Retrying..."); + // Implement retry logic + break; + default: + System.err.println("Unexpected error: " + e.getMessage()); + } + throw e; +} catch (SdkException e) { + System.err.println("SDK error: " + e.getMessage()); + throw e; +} +``` + +## Scenario Requirements +- ✅ **ALWAYS** read and implement based on `scenarios/basics/{service}/SPECIFICATION.md` +- ✅ **ALWAYS** include descriptive comment block at top explaining scenario steps from specification +- ✅ **ALWAYS** use Scanner for user interaction +- ✅ **ALWAYS** use service actions classes for all AWS operations +- ✅ **ALWAYS** implement proper cleanup in finally block +- ✅ **ALWAYS** break scenario into logical phases per specification +- ✅ **ALWAYS** include error handling per specification's Errors section +- ✅ **ALWAYS** provide educational context and explanations from specification +- ✅ **ALWAYS** handle edge cases (no resources found, etc.) as specified + +## Implementation Workflow + +### Step-by-Step Implementation Process +1. **Read Specification**: Study `scenarios/basics/{service}/SPECIFICATION.md` thoroughly +2. **Extract API Actions**: Note all API actions listed in "API Actions Used" section +3. **Map to Actions Methods**: Ensure actions class has methods for all required actions +4. **Implement Phases**: Follow the "Proposed example structure" section exactly +5. **Add Error Handling**: Implement error handling per the "Errors" section +6. **Test Against Specification**: Verify implementation matches specification requirements + +### Specification Sections to Implement +- **API Actions Used**: All operations must be available in actions class +- **Proposed example structure**: Direct mapping to scenario phases +- **Setup**: Exact setup steps and resource creation +- **Demonstration**: Specific operations to demonstrate +- **Examination**: Data analysis and filtering requirements +- **Cleanup**: Resource cleanup options and user choices +- **Errors**: Specific error codes and handling strategies + +## Error Handling in Scenarios +- **Follow specification error table**: Implement exact error handling per specification +- Catch and display user-friendly error messages per specification guidance +- Continue scenario execution when possible as specified +- Provide guidance on resolving issues from specification +- Ensure cleanup runs even if errors occur + +## Educational Elements +- **Use specification descriptions**: Explain operations using specification language +- Show before/after states as outlined in specification +- Provide context about service capabilities from specification +- Include tips and best practices mentioned in specification +- Follow the educational flow described in specification structure \ No newline at end of file diff --git a/steering_docs/java-tech/hello.md b/steering_docs/java-tech/hello.md new file mode 100644 index 00000000000..a39453f4c5f --- /dev/null +++ b/steering_docs/java-tech/hello.md @@ -0,0 +1,268 @@ +# Java Hello Examples Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Java-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Java-premium-KB", "Java implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate simple "Hello" examples that demonstrate basic service connectivity and the most fundamental operation using direct AWS SDK for Java V2 client calls. + +## Requirements +- **MANDATORY**: Every AWS service MUST include a "Hello" scenario +- **Simplicity**: Should be the most basic, minimal example possible +- **Standalone**: Must work independently of other examples +- **Direct Client**: Use AWS SDK client directly, no actions classes needed + +## File Structure +``` +javav2/example_code/{service}/ +├── src/main/java/com/example/{service}/ +│ └── Hello{Service}.java # Hello example file +``` + +## Hello Example Pattern +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.{service}.{Service}Client; +import software.amazon.awssdk.services.{service}.model.*; +import software.amazon.awssdk.core.exception.SdkException; + +/** + * Before running this Java V2 code example, set up your development + * environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html + * + * This example shows how to get started with {AWS Service} by {basic operation description}. + */ + +// snippet-start:[{service}.java2.hello.main] +public class Hello{Service} { + + public static void main(String[] args) { + final String usage = """ + Usage: + + + Where: + region - The AWS region (for example, us-east-1). + """; + + if (args.length != 1) { + System.out.println(usage); + System.exit(1); + } + + String region = args[0]; + Region awsRegion = Region.of(region); + {Service}Client {service}Client = {Service}Client.builder() + .region(awsRegion) + .build(); + + hello{Service}({service}Client); + {service}Client.close(); + } + + /** + * Invokes a {AWS Service} operation to {basic operation description}. + * + * @param {service}Client the {AWS Service} client to use for the operation + */ + public static void hello{Service}({Service}Client {service}Client) { + try { + // Perform the most basic operation for this service + {BasicOperation}Request request = {BasicOperation}Request.builder() + .build(); + + {BasicOperation}Response response = {service}Client.{basicOperation}(request); + + System.out.println("Hello, {AWS Service}!"); + + // Display appropriate result information + if (response.has{ResultField}()) { + System.out.println("Found " + response.{resultField}().size() + " {resources}."); + response.{resultField}().forEach(resource -> + System.out.println(" - " + resource.{resourceName}()) + ); + } else { + System.out.println("{AWS Service} is available and ready to use."); + } + + } catch ({Service}Exception e) { + System.err.println("{AWS Service} error occurred: " + e.awsErrorDetails().errorMessage()); + System.exit(1); + } catch (SdkException e) { + System.err.println("SDK error occurred: " + e.getMessage()); + System.exit(1); + } + } +} +// snippet-end:[{service}.java2.hello.main] +``` + +## Hello Examples by Service Type + +### List-Based Services (S3, DynamoDB, etc.) +- **Operation**: List primary resources (buckets, tables, etc.) +- **Message**: Show count and names of resources + +### Status-Based Services (GuardDuty, Config, etc.) +- **Operation**: Check service status or list detectors/configurations +- **Message**: Show service availability and basic status + +### Compute Services (EC2, Lambda, etc.) +- **Operation**: List instances/functions or describe regions +- **Message**: Show available resources or regions + +## Service-Specific Hello Examples + +### For Services with List Operations +```java +public static void hello{Service}({Service}Client {service}Client) { + try { + List{Resources}Request request = List{Resources}Request.builder().build(); + List{Resources}Response response = {service}Client.list{Resources}(request); + + System.out.println("Hello, {AWS Service}!"); + System.out.println("Found " + response.{resources}().size() + " {resources}."); + + response.{resources}().forEach(resource -> + System.out.println(" - " + resource.{resourceName}()) + ); + + } catch ({Service}Exception e) { + System.err.println("{AWS Service} error: " + e.awsErrorDetails().errorMessage()); + System.exit(1); + } +} +``` + +### For Services with Status Operations +```java +public static void hello{Service}({Service}Client {service}Client) { + try { + Get{Service}StatusRequest request = Get{Service}StatusRequest.builder().build(); + Get{Service}StatusResponse response = {service}Client.get{Service}Status(request); + + System.out.println("Hello, {AWS Service}!"); + System.out.println("Service status: " + response.status()); + System.out.println("{AWS Service} is ready to use."); + + } catch ({Service}Exception e) { + System.err.println("{AWS Service} error: " + e.awsErrorDetails().errorMessage()); + System.exit(1); + } +} +``` + +### For Services with Describe Operations +```java +public static void hello{Service}({Service}Client {service}Client) { + try { + Describe{Resources}Request request = Describe{Resources}Request.builder() + .maxResults(10) + .build(); + Describe{Resources}Response response = {service}Client.describe{Resources}(request); + + System.out.println("Hello, {AWS Service}!"); + System.out.println("Found " + response.{resources}().size() + " {resources}."); + + response.{resources}().forEach(resource -> + System.out.println(" - " + resource.{resourceId}() + " (" + resource.state() + ")") + ); + + } catch ({Service}Exception e) { + System.err.println("{AWS Service} error: " + e.awsErrorDetails().errorMessage()); + System.exit(1); + } +} +``` + +## Error Handling Requirements + +### Standard Error Handling Pattern +```java +try { + // AWS operation + response = {service}Client.operation(request); + +} catch ({Service}Exception e) { + // Service-specific errors + String errorCode = e.awsErrorDetails().errorCode(); + switch (errorCode) { + case "UnauthorizedOperation": + System.err.println("You don't have permission to access {AWS Service}."); + break; + case "InvalidParameterValue": + System.err.println("Invalid parameter provided to {AWS Service}."); + break; + default: + System.err.println("{AWS Service} error: " + e.awsErrorDetails().errorMessage()); + } + System.exit(1); + +} catch (SdkException e) { + // General SDK errors (network, credentials, etc.) + System.err.println("SDK error: " + e.getMessage()); + System.exit(1); +} +``` + +## Validation Requirements +- ✅ **Must run without errors** (with proper credentials) +- ✅ **Must handle credential issues gracefully** +- ✅ **Must display meaningful output** +- ✅ **Must use direct AWS SDK client calls** +- ✅ **Must include proper snippet tags** +- ✅ **Must accept region as command line argument** +- ✅ **Must close client resources properly** + +## Common Patterns +- Always use `{Service}Client.builder().region(awsRegion).build()` for client creation +- Include comprehensive error handling for both service and SDK exceptions +- Provide user-friendly output messages +- Handle command line arguments properly +- Close client resources in main method +- Keep it as simple as possible - no additional classes or complexity +- Use proper Java naming conventions (PascalCase for classes, camelCase for methods) + +## Build Configuration +Ensure the service dependency is included in `pom.xml`: + +```xml + + software.amazon.awssdk + {service} + ${aws.java.sdk.version} + +``` + +## Testing Requirements +- ✅ **Must compile without errors** +- ✅ **Must run with valid AWS credentials** +- ✅ **Must handle invalid regions gracefully** +- ✅ **Must display appropriate output for empty results** +- ✅ **Must exit cleanly on errors** \ No newline at end of file diff --git a/steering_docs/java-tech/metadata.md b/steering_docs/java-tech/metadata.md new file mode 100644 index 00000000000..a3d987f9887 --- /dev/null +++ b/steering_docs/java-tech/metadata.md @@ -0,0 +1,267 @@ +# Java Metadata Generation + +## Purpose +Generate documentation metadata files that integrate with AWS Documentation pipeline for snippet extraction and cross-referencing. + +## Requirements +- **Specification First**: Always check service specification for exact metadata keys +- **Snippet Tags**: Match snippet tags in code exactly +- **Complete Coverage**: Include all actions and scenarios from specification + +## File Structure +``` +.doc_gen/metadata/ +├── {service}_metadata.yaml # Service metadata file +``` + +## Metadata Discovery Process + +### Step 1: Check Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first for metadata requirements. + +Look for the metadata table: +```markdown +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`CreateDetector` |{service}_metadata.yaml |{service}_CreateDetector | +|`GetDetector` |{service}_metadata.yaml |{service}_GetDetector | +|`Service Basics Scenario` |{service}_metadata.yaml |{service}_Scenario | +``` + +### Step 2: Use Exact Metadata Keys +**NEVER** create custom metadata keys when specification defines them. Use the exact keys from the specification table. + +## Metadata File Pattern +```yaml +# .doc_gen/metadata/{service}_metadata.yaml + +{service}_CreateResource: + title: Create a &{ServiceAbbrev}; resource + title_abbrev: Create a resource + synopsis: create a &{ServiceAbbrev}; resource. + category: Actions + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.java2.create_resource.main + services: + {service}: {CreateResource} + +{service}_GetResource: + title: Get a &{ServiceAbbrev}; resource + title_abbrev: Get a resource + synopsis: get a &{ServiceAbbrev}; resource. + category: Actions + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.java2.get_resource.main + services: + {service}: {GetResource} + +{service}_Scenario: + title: Get started with &{ServiceAbbrev}; resources + title_abbrev: Get started with resources + synopsis: learn the basics of &{ServiceAbbrev}; by creating resources and managing them. + category: Scenarios + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/{service} + sdkguide: + excerpts: + - description: Create a {Service} actions class to manage operations. + snippet_tags: + - {service}.java2.{service}_actions.main + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - {service}.java2.{service}_scenario.main + services: + {service}: {CreateResource, GetResource, ListResources, DeleteResource} + +{service}_Hello: + title: Hello &{ServiceAbbrev}; + title_abbrev: Hello &{ServiceAbbrev}; + synopsis: get started using &{ServiceAbbrev};. + category: Hello + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.java2.hello.main + services: + {service}: {ListResources} +``` + +## Snippet Tag Requirements + +### Code Snippet Tags +All code must include proper snippet tags that match metadata: + +```java +// snippet-start:[{service}.java2.{action_name}.main] +public static void {actionMethod}({Service}Client {service}Client) { + // Action implementation +} +// snippet-end:[{service}.java2.{action_name}.main] +``` + +### Actions Class Tags +```java +// snippet-start:[{service}.java2.{service}_actions.main] +public class {Service}Actions { + // Actions class implementation +} +// snippet-end:[{service}.java2.{service}_actions.main] +``` + +### Scenario Tags +```java +// snippet-start:[{service}.java2.{service}_scenario.main] +public class {Service}Scenario { + // Scenario class implementation +} +// snippet-end:[{service}.java2.{service}_scenario.main] +``` + +### Hello Tags +```java +// snippet-start:[{service}.java2.hello.main] +public class Hello{Service} { + // Hello implementation +} +// snippet-end:[{service}.java2.hello.main] +``` + +## Service Abbreviations + +Common service abbreviations for metadata: +- **GuardDuty**: GD +- **DynamoDB**: DDB +- **Simple Storage Service**: S3 +- **Elastic Compute Cloud**: EC2 +- **Identity and Access Management**: IAM +- **Key Management Service**: KMS +- **Simple Notification Service**: SNS +- **Simple Queue Service**: SQS +- **Inspector**: Inspector + +## Metadata Categories + +### Actions +Individual service operations (CreateResource, GetResource, etc.) + +### Scenarios +Multi-step workflows demonstrating service usage + +### Hello +Simple introduction examples + +### Cross-service +Examples spanning multiple AWS services + +## Java-Specific Metadata Fields + +### SDK Version +Always use `sdk_version: 2` for Java V2 SDK examples + +### GitHub Path +Use `javav2/example_code/{service}` for Java V2 examples + +### SDK Guide +Include `sdkguide:` field when documentation links are available + +### Snippet Tag Format +Use format: `{service}.java2.{operation}.main` + +## Metadata Validation + +### Required Fields +- ✅ **title**: Descriptive title with service abbreviation +- ✅ **title_abbrev**: Shortened title +- ✅ **synopsis**: Brief description of what the example does +- ✅ **category**: Actions, Scenarios, Hello, or Cross-service +- ✅ **languages.Java.versions**: SDK version information +- ✅ **github**: Path to example code +- ✅ **snippet_tags**: Matching tags from code +- ✅ **services**: Service operations used + +### Validation Commands +```bash +# Validate metadata with writeme tool +cd .tools/readmes +python -m writeme --languages Java:2 --services {service} +``` + +## Common Metadata Errors +- ❌ **Custom metadata keys** when specification exists +- ❌ **Mismatched snippet tags** between code and metadata +- ❌ **Missing service operations** in services section +- ❌ **Incorrect github paths** to example code +- ❌ **Wrong service abbreviations** in titles +- ❌ **Missing required fields** in metadata structure +- ❌ **Wrong SDK version** (should be 2 for Java V2) + +## Metadata Generation Workflow +1. **Read specification** for exact metadata requirements +2. **Extract metadata table** from specification +3. **Create metadata file** using specification keys +4. **Add snippet tags** to all code files +5. **Validate metadata** with writeme tool +6. **Fix any validation errors** before completion + +## Java-Specific Considerations + +### Package Structure +Java examples are organized in packages: +``` +javav2/example_code/{service}/src/main/java/com/example/{service}/ +``` + +### Class Naming +- Hello examples: `Hello{Service}.java` +- Actions classes: `{Service}Actions.java` +- Scenarios: `{Service}Scenario.java` + +### Snippet Tag Placement +Place snippet tags around entire classes or methods: +```java +// snippet-start:[{service}.java2.{actionName}.main] +public class Hello{Service} { + // Entire class content +} +// snippet-end:[{service}.java2.{actionName}.main] +``` + +### Multiple Excerpts +For complex examples, use multiple excerpts: +```yaml +excerpts: + - description: Create a {Service} actions class to manage operations. + snippet_tags: + - {service}.java2.{service}_actions.main + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - {service}.java2.{service}_scenario.main + +``` diff --git a/steering_docs/java-tech/orchestration.md b/steering_docs/java-tech/orchestration.md new file mode 100644 index 00000000000..098c40ffa20 --- /dev/null +++ b/steering_docs/java-tech/orchestration.md @@ -0,0 +1,338 @@ +# Java Code Generation Orchestration + +## Purpose +Coordinate the modular components to generate complete AWS SDK for Java V2 code examples. Each component can be used independently or in sequence. + +## Component Dependencies + +```mermaid +graph TD + A[Knowledge Base Consultation] --> B[Hello Example] + A --> C[Actions Class] + A --> D[Scenario] + + C --> E[Tests - Unit Tests] + E --> F[Tests - Integration Tests] + E --> G[Tests - Scenario Tests] + + B --> H[Metadata Generation] + C --> H + D --> H + + H --> I[README Generation] + + J[Service Specification] --> H + J --> C + J --> D +``` + +## Execution Workflows + +### Full Service Implementation +Complete implementation of a new AWS service: + +```bash +# 1. Knowledge Base Consultation (MANDATORY FIRST) +# Use ListKnowledgeBases + QueryKnowledgeBases for standards and patterns + +# 2. Generate Core Components +# - Hello example: Hello{Service}.java +# - Actions class: {Service}Actions.java +# - Scenario: {Service}Scenario.java +# - Build configuration: pom.xml updates + +# 3. Generate Test Suite +# - Unit tests: {Service}ActionsTest.java +# - Integration tests: {Service}IntegrationTest.java +# - Scenario tests: {Service}ScenarioTest.java + +# 4. Generate Metadata +# - Read service specification for exact metadata keys +# - Create .doc_gen/metadata/{service}_metadata.yaml + +# 5. Generate Documentation +# - Run writeme tool to create/update README.md +``` + +### Individual Component Updates + +#### Update Hello Example Only +```bash +# Focus: hello.md guidance +# Files: Hello{Service}.java +# Validation: Compile and run hello example +``` + +#### Update Actions Class Only +```bash +# Focus: actions.md guidance +# Files: {Service}Actions.java +# Validation: Run unit tests for actions methods +``` + +#### Update Scenario Only +```bash +# Focus: scenario.md guidance +# Files: {Service}Scenario.java +# Validation: Run scenario tests, check user interaction +``` + +#### Update Tests Only +```bash +# Focus: tests.md guidance +# Files: All test files in test/ directory +# Validation: Run mvn test with all test categories +``` + +#### Update Metadata Only +```bash +# Focus: metadata.md guidance +# Files: .doc_gen/metadata/{service}_metadata.yaml +# Validation: Run writeme tool validation +``` + +#### Update Documentation Only +```bash +# Focus: readme.md guidance +# Files: README.md (generated) +# Validation: Check README completeness and accuracy +``` + +## Quality Gates + +### Component-Level Validation +Each component has specific validation requirements: + +#### Hello Example Validation +```bash +cd javav2/example_code/{service} +mvn compile exec:java -Dexec.mainClass="com.example.{service}.Hello{Service}" -Dexec.args="us-east-1" +``` + +#### Actions Class Validation +```bash +cd javav2/example_code/{service} +mvn compile +# Verify compilation succeeds and no syntax errors +``` + +#### Scenario Validation +```bash +cd javav2/example_code/{service} +mvn compile exec:java -Dexec.mainClass="com.example.{service}.{Service}Scenario" -Dexec.args="us-east-1" +``` + +#### Test Validation +```bash +cd javav2/example_code/{service} +mvn test -Dtest="{Service}ActionsTest" +mvn test -Dtest="{Service}IntegrationTest" -Dgroups="integration" +``` + +#### Code Quality Validation +```bash +cd javav2/example_code/{service} +mvn checkstyle:check +mvn spotbugs:check +``` + +#### Documentation Validation +```bash +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Java:2 --services {service} +``` + +### Integration Validation +Full integration testing across all components: + +```bash +# 1. All unit tests pass +cd javav2/example_code/{service} +mvn test -Dtest="*Test" -Dgroups="!integration" + +# 2. All integration tests pass +mvn test -Dtest="*IntegrationTest" -Dgroups="integration" + +# 3. All examples execute successfully +mvn compile exec:java -Dexec.mainClass="com.example.{service}.Hello{Service}" -Dexec.args="us-east-1" +mvn compile exec:java -Dexec.mainClass="com.example.{service}.{Service}Scenario" -Dexec.args="us-east-1" + +# 4. Code quality passes +mvn checkstyle:check spotbugs:check + +# 5. Documentation generates successfully +cd .tools/readmes && source .venv/bin/activate && python -m writeme --languages Java:2 --services {service} +``` + +## Component Selection Guide + +### When to Use Individual Components + +#### Hello Example Only +- Quick service introduction needed +- Testing basic service connectivity +- Creating minimal working example + +#### Actions Class Only +- Need reusable service operations +- Building foundation for other examples +- Focusing on error handling patterns + +#### Scenario Only +- Demonstrating complete workflows +- Educational/tutorial content +- Interactive user experiences + +#### Tests Only +- Improving test coverage +- Adding new test cases +- Fixing test infrastructure + +#### Metadata Only +- Documentation pipeline integration +- Updating snippet references +- Fixing metadata validation errors + +#### Documentation Only +- README updates needed +- Documentation refresh +- Link validation and updates + +### When to Use Full Workflow +- New service implementation +- Complete service overhaul +- Major structural changes +- Initial service setup + +## Error Recovery + +### Component Failure Handling +If any component fails, you can: + +1. **Fix and retry** the specific component +2. **Skip and continue** with other components +3. **Rollback changes** and restart from known good state + +### Common Recovery Scenarios + +#### Compilation Failures +```bash +# Fix compilation issues and re-run +cd javav2/example_code/{service} +mvn clean compile +``` + +#### Test Failures +```bash +# Fix test issues and re-run +mvn test -Dtest="FailingTest" -Dgroups="unit" +``` + +#### Metadata Validation Failures +```bash +# Check metadata syntax +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Validate against specification +# Compare with scenarios/basics/{service}/SPECIFICATION.md +``` + +#### Documentation Generation Failures +```bash +# Check for missing dependencies +cd .tools/readmes && source .venv/bin/activate && pip list + +# Validate metadata first +python -m writeme --languages Java:2 --services {service} --verbose +``` + +## Build System Integration + +### Maven Configuration +Ensure proper Maven configuration in `pom.xml`: + +```xml + + + software.amazon.awssdk + {service} + ${aws.java.sdk.version} + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 17 + 17 + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + !integration + + + + +``` + +### Test Execution Profiles +```xml + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + integration + + + + + + +``` + +## CI/CD Integration + +### Automated Validation Pipeline +```bash +# In CI/CD pipeline, validate all components +cd javav2/example_code/{service} + +# 1. Compile all code +mvn clean compile + +# 2. Run unit tests +mvn test -Dgroups="!integration" + +# 3. Run integration tests (if credentials available) +mvn test -Dgroups="integration" + +# 4. Check code quality +mvn checkstyle:check spotbugs:check + +# 5. Validate documentation +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Java:2 --services {service} --check +``` + +This modular approach allows for targeted updates, easier debugging, and more maintainable code generation processes while maintaining Java-specific build and testing requirements. \ No newline at end of file diff --git a/steering_docs/java-tech/readme_writeme.md b/steering_docs/java-tech/readme_writeme.md new file mode 100644 index 00000000000..572e32f89c2 --- /dev/null +++ b/steering_docs/java-tech/readme_writeme.md @@ -0,0 +1,280 @@ +# Java README/WRITEME and Documentation Generation + +## Purpose +Generate and update README files and documentation using the writeme tool to ensure consistency and completeness. + +## Requirements +- **Automated Generation**: Use writeme tool for README generation +- **Metadata Dependency**: Requires complete metadata files +- **Virtual Environment**: Run writeme in isolated environment +- **Validation**: Ensure all documentation is up-to-date + +## File Structure +``` +javav2/example_code/{service}/ +├── README.md # Generated service README +├── pom.xml # Maven dependencies +└── {service}_metadata.yaml # Metadata (in .doc_gen/metadata/) +``` + +## README Generation Process + +### Step 1: Setup Writeme Environment +```bash +cd .tools/readmes + +# Create virtual environment +python -m venv .venv + +# Activate environment (Linux/macOS) +source .venv/bin/activate + +# Activate environment (Windows) +.venv\Scripts\activate + +# Install dependencies +python -m pip install -r requirements_freeze.txt +``` + +### Step 2: Generate README +```bash +# Generate README for specific service +python -m writeme --languages Java:2 --services {service} +``` + +### Step 3: Validate Generation +- ✅ **README.md created/updated** in service directory +- ✅ **No generation errors** in writeme output +- ✅ **All examples listed** in README +- ✅ **Proper formatting** and structure +- ✅ **Working links** to code files + +## README Content Structure + +### Generated README Sections +1. **Service Overview**: Description of AWS service +2. **Code Examples**: List of available examples +3. **Prerequisites**: Setup requirements +4. **Installation**: Dependency installation +5. **Usage**: How to run examples +6. **Tests**: Testing instructions +7. **Additional Resources**: Links to documentation + +### Example README Content +```markdown +# {AWS Service} code examples for the SDK for Java 2.x + +## Overview + +This is a workspace where you can find the following AWS SDK for Java 2.x +{AWS Service} examples. + +## ⚠ Important + +* Running this code might result in charges to your AWS account. +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. + +## Code examples + +### Actions + +The following examples show you how to perform actions using the AWS SDK for Java 2.x. + +* [Create a resource](src/main/java/com/example/{service}/{Service}Actions.java#L123) (`CreateResource`) +* [Get a resource](src/main/java/com/example/{service}/{Service}Actions.java#L456) (`GetResource`) + +### Scenarios + +The following examples show you how to implement common scenarios. + +* [Get started with resources](src/main/java/com/example/{service}/{Service}Scenario.java) - Learn the basics by creating and managing resources. + +### Hello + +* [Hello {Service}](src/main/java/com/example/{service}/Hello{Service}.java) - Get started with {AWS Service}. + +## Prerequisites + +- You must have an AWS account, and have your default credentials and AWS Region configured. +- Java 17 or later +- Maven 3.6 or later + +## Install + +To build and run the examples, navigate to the directory that contains a `pom.xml` file and run the following command: + +``` +mvn compile +``` + +## Run the examples + +### Instructions + +All examples can be run individually. For example: + +``` +mvn exec:java -Dexec.mainClass="com.example.{service}.Hello{Service}" -Dexec.args="us-east-1" +``` + +### Hello {Service} + +This example shows you how to get started using {AWS Service}. + +``` +mvn exec:java -Dexec.mainClass="com.example.{service}.Hello{Service}" -Dexec.args="us-east-1" +``` + +### Get started with {Service} resources + +This interactive scenario runs at a command prompt and shows you how to use {AWS Service} to do the following: + +1. Create a resource +2. Use the resource +3. Clean up resources + +``` +mvn exec:java -Dexec.mainClass="com.example.{service}.{Service}Scenario" -Dexec.args="us-east-1" +``` + +## Run the tests + +Unit tests in this module use JUnit 5. To run all of the tests, +run the following in your [GitHub root]/javav2/example_code/{service} folder. + +``` +mvn test +``` + +## Additional resources + +- [{AWS Service} User Guide](https://docs.aws.amazon.com/{service}/latest/ug/) +- [{AWS Service} API Reference](https://docs.aws.amazon.com/{service}/latest/APIReference/) +- [AWS SDK for Java 2.x ({AWS Service})](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/{service}/package-summary.html) +``` + +## Documentation Dependencies + +### Required Files for README Generation +- ✅ **Metadata file**: `.doc_gen/metadata/{service}_metadata.yaml` +- ✅ **Code files**: All referenced Java files must exist +- ✅ **Snippet tags**: All snippet tags in metadata must exist in code +- ✅ **Build file**: `pom.xml` with dependencies + +### Metadata Integration +The writeme tool uses metadata to: +- Generate example lists and descriptions +- Create links to specific code sections +- Include proper service information +- Format documentation consistently + +## Troubleshooting README Generation + +### Common Issues +- **Missing metadata**: Ensure metadata file exists and is valid +- **Broken snippet tags**: Verify all snippet tags exist in code +- **File not found**: Check all file paths in metadata +- **Invalid YAML**: Validate metadata YAML syntax + +### Error Resolution +```bash +# Check for metadata errors +python -m writeme --languages Java:2 --services {service} --verbose + +# Validate specific metadata file +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Check for missing snippet tags +grep -r "snippet-start" javav2/example_code/{service}/ +``` + +## README Maintenance + +### When to Regenerate README +- ✅ **After adding new examples** +- ✅ **After updating metadata** +- ✅ **After changing code structure** +- ✅ **Before committing changes** +- ✅ **During regular maintenance** + +### README Quality Checklist +- ✅ **All examples listed** and properly linked +- ✅ **Prerequisites accurate** and complete +- ✅ **Installation instructions** work correctly +- ✅ **Usage examples** are clear and correct +- ✅ **Links functional** and point to right locations +- ✅ **Formatting consistent** with other services + +## Java-Specific README Elements + +### Maven Commands +README includes proper Maven commands for: +- **Compilation**: `mvn compile` +- **Execution**: `mvn exec:java -Dexec.mainClass="..." -Dexec.args="..."` +- **Testing**: `mvn test` + +### Prerequisites +Java-specific prerequisites: +- Java 17 or later +- Maven 3.6 or later +- AWS credentials configured + +### Code Links +Links point to specific Java files: +- Actions: `src/main/java/com/example/{service}/{Service}Actions.java` +- Scenarios: `src/main/java/com/example/{service}/{Service}Scenario.java` +- Hello: `src/main/java/com/example/{service}/Hello{Service}.java` + +## Integration with CI/CD + +### Automated README Validation +```bash +# In CI/CD pipeline, validate README is up-to-date +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Java:2 --services {service} --check + +# Exit with error if README needs updates +if git diff --exit-code javav2/example_code/{service}/README.md; then + echo "README is up-to-date" +else + echo "README needs to be regenerated" + exit 1 +fi +``` + +### Build Integration +Ensure README generation is part of the build process: + +```xml + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + generate-readme + validate + + exec + + + python + .tools/readmes + + -m + writeme + --languages + Java:2 + --services + {service} + + + + + +``` + +This ensures documentation stays synchronized with code changes and maintains consistency across all Java examples. \ No newline at end of file diff --git a/steering_docs/java-tech/tests.md b/steering_docs/java-tech/tests.md new file mode 100644 index 00000000000..dcee4ecebb9 --- /dev/null +++ b/steering_docs/java-tech/tests.md @@ -0,0 +1,476 @@ +# Java Test Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Java-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Java-premium-KB", "Java implementation patterns testing") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate comprehensive test suites including unit tests, integration tests, and scenario tests using JUnit 5 and Mockito for AWS SDK for Java V2. + +## Requirements +- **JUnit 5**: Use JUnit Jupiter for all tests +- **Mockito**: Mock AWS SDK clients for unit tests +- **Complete Data**: Use complete AWS data structures in tests +- **Test Groups**: Use JUnit tags for test categorization +- **Error Coverage**: Test all error conditions from specification + +## File Structure +``` +javav2/example_code/{service}/src/test/java/ +├── {Service}ActionsTest.java # Unit tests for actions +├── {Service}IntegrationTest.java # Integration tests +└── {Service}ScenarioTest.java # Scenario tests +``` + +## Maven Test Configuration + +### Dependencies in pom.xml +```xml + + + + software.amazon.awssdk + {service} + ${aws.java.sdk.version} + + + + + org.junit.jupiter + junit-jupiter + 5.10.0 + test + + + org.mockito + mockito-core + 5.5.0 + test + + + org.mockito + mockito-junit-jupiter + 5.5.0 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + !integration + + + + + + + + integration + + + + org.apache.maven.plugins + maven-surefire-plugin + + integration + + + + + + +``` + +## Unit Test Pattern +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import software.amazon.awssdk.services.{service}.{Service}Client; +import software.amazon.awssdk.services.{service}.model.*; +import software.amazon.awssdk.core.exception.SdkException; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class {Service}ActionsTest { + + @Mock + private {Service}Client {service}Client; + + private {Service}Actions {service}Actions; + + @BeforeEach + void setUp() { + {service}Actions = new {Service}Actions(); + } + + @Test + void test{ActionName}_Success() { + // Arrange + String testParam = "test-value"; + {ActionName}Response expectedResponse = {ActionName}Response.builder() + .{responseField}("response-value") + .build(); + + when({service}Client.{actionName}(any({ActionName}Request.class))) + .thenReturn(expectedResponse); + + // Act + {ActionName}Response result = {service}Actions.{actionName}({service}Client, testParam); + + // Assert + assertNotNull(result); + assertEquals("response-value", result.{responseField}()); + + verify({service}Client).{actionName}(any({ActionName}Request.class)); + } + + @ParameterizedTest + @ValueSource(strings = {"BadRequestException", "InternalServerErrorException", "ResourceNotFoundException"}) + void test{ActionName}_ServiceException(String errorCode) { + // Arrange + String testParam = "test-value"; + {Service}Exception serviceException = ({Service}Exception) {Service}Exception.builder() + .awsErrorDetails(AwsErrorDetails.builder() + .errorCode(errorCode) + .errorMessage("Test error message") + .build()) + .build(); + + when({service}Client.{actionName}(any({ActionName}Request.class))) + .thenThrow(serviceException); + + // Act & Assert + {Service}Exception exception = assertThrows({Service}Exception.class, () -> + {service}Actions.{actionName}({service}Client, testParam)); + + assertEquals(errorCode, exception.awsErrorDetails().errorCode()); + verify({service}Client).{actionName}(any({ActionName}Request.class)); + } + + @Test + void test{ActionName}_SdkException() { + // Arrange + String testParam = "test-value"; + SdkException sdkException = SdkException.builder() + .message("SDK error occurred") + .build(); + + when({service}Client.{actionName}(any({ActionName}Request.class))) + .thenThrow(sdkException); + + // Act & Assert + SdkException exception = assertThrows(SdkException.class, () -> + {service}Actions.{actionName}({service}Client, testParam)); + + assertEquals("SDK error occurred", exception.getMessage()); + verify({service}Client).{actionName}(any({ActionName}Request.class)); + } +} +``` + +## Complete AWS Data Structures + +### CRITICAL: Use Complete AWS Response Data +```java +// ❌ WRONG - Minimal data that fails validation +List<{Resource}> resources = List.of( + {Resource}.builder() + .{resourceId}("resource-1") + .build() +); + +// ✅ CORRECT - Complete AWS data structure +List<{Resource}> resources = List.of( + {Resource}.builder() + .{resourceId}("resource-1") + .{resourceName}("test-resource") + .{resourceArn}("arn:aws:service:region:account:resource/resource-1") + .{resourceStatus}({ResourceStatus}.ACTIVE) + .{createdAt}(Instant.now()) + .{updatedAt}(Instant.now()) + .{tags}(Map.of("Environment", "Test")) + .build() +); +``` + +## Integration Test Pattern +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.AfterAll; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.{service}.{Service}Client; +import software.amazon.awssdk.services.{service}.model.*; + +import static org.junit.jupiter.api.Assertions.*; + +@Tag("integration") +class {Service}IntegrationTest { + + private static {Service}Client {service}Client; + private static {Service}Actions {service}Actions; + private static String testResourceId; + + @BeforeAll + static void setUp() { + {service}Client = {Service}Client.builder() + .region(Region.US_EAST_1) + .build(); + {service}Actions = new {Service}Actions(); + } + + @AfterAll + static void tearDown() { + // Clean up test resources + if (testResourceId != null) { + try { + {service}Actions.deleteResource({service}Client, testResourceId); + } catch (Exception e) { + // Ignore cleanup errors + } + } + if ({service}Client != null) { + {service}Client.close(); + } + } + + @Test + void testResourceLifecycle() { + try { + // Create resource + testResourceId = {service}Actions.createResource({service}Client); + assertNotNull(testResourceId); + + // Get resource + {Resource} resource = {service}Actions.getResource({service}Client, testResourceId); + assertNotNull(resource); + assertEquals(testResourceId, resource.{resourceId}()); + + // List resources (should include our test resource) + List<{Resource}> resources = {service}Actions.listResources({service}Client); + assertTrue(resources.stream() + .anyMatch(r -> testResourceId.equals(r.{resourceId}()))); + + } catch (Exception e) { + fail("Integration test failed: " + e.getMessage()); + } + } + + @Test + void testServiceConnectivity() { + // Test basic service connectivity + assertDoesNotThrow(() -> { + List<{Resource}> resources = {service}Actions.listResources({service}Client); + assertNotNull(resources); + }); + } +} +``` + +## Scenario Test Pattern +```java +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.{service}; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.{service}.{Service}Client; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.jupiter.api.Assertions.*; + +@Tag("integration") +class {Service}ScenarioTest { + + private {Service}Client {service}Client; + private ByteArrayOutputStream outputStream; + private PrintStream originalOut; + + @BeforeEach + void setUp() { + {service}Client = {Service}Client.builder() + .region(Region.US_EAST_1) + .build(); + + // Capture System.out for testing + outputStream = new ByteArrayOutputStream(); + originalOut = System.out; + System.setOut(new PrintStream(outputStream)); + } + + @AfterEach + void tearDown() { + System.setOut(originalOut); + if ({service}Client != null) { + {service}Client.close(); + } + } + + @Test + void testScenarioWithMockedInput() { + // Mock user inputs for automated testing + String simulatedInput = "n\nn\ny\n"; // No existing resource, no details, yes cleanup + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes())); + + // Run scenario + assertDoesNotThrow(() -> { + {Service}Scenario.main(new String[]{"us-east-1"}); + }); + + // Verify output contains expected messages + String output = outputStream.toString(); + assertTrue(output.contains("Welcome to the {AWS Service} basics scenario!")); + assertTrue(output.contains("Setting up {AWS Service}")); + } + + @Test + void testScenarioWithExistingResources() { + // Create a test resource first + String testResourceId = null; + try { + {Service}Actions actions = new {Service}Actions(); + testResourceId = actions.createResource({service}Client); + + // Mock user inputs to use existing resource + String simulatedInput = "y\nn\ny\n"; // Yes existing, no details, yes cleanup + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes())); + + // Run scenario + assertDoesNotThrow(() -> { + {Service}Scenario.main(new String[]{"us-east-1"}); + }); + + String output = outputStream.toString(); + assertTrue(output.contains("Found")); + assertTrue(output.contains("existing resource")); + + } finally { + // Clean up test resource + if (testResourceId != null) { + try { + new {Service}Actions().deleteResource({service}Client, testResourceId); + } catch (Exception e) { + // Ignore cleanup errors + } + } + } + } +} +``` + +## Test Execution Commands + +### Unit Tests Only +```bash +cd javav2/example_code/{service} +mvn test -Dgroups="!integration" +``` + +### Integration Tests Only +```bash +cd javav2/example_code/{service} +mvn test -Dgroups="integration" +``` + +### All Tests +```bash +cd javav2/example_code/{service} +mvn test +``` + +### Specific Test Class +```bash +mvn test -Dtest="{Service}ActionsTest" +``` + +## Test Requirements Checklist +- ✅ **JUnit 5 annotations** (@Test, @BeforeEach, @AfterEach) +- ✅ **Mockito for unit tests** (@Mock, @ExtendWith(MockitoExtension.class)) +- ✅ **Complete AWS data structures** in all tests +- ✅ **Proper test tags** (@Tag("integration")) +- ✅ **Error condition coverage** per specification +- ✅ **Integration test cleanup** (try/finally blocks) +- ✅ **Region specification** (Region.US_EAST_1) +- ✅ **Resource lifecycle testing** (create, read, delete) +- ✅ **Parameterized tests** for multiple error conditions + +## Test Categories + +### Unit Tests +- ✅ **Mock AWS clients** using Mockito +- ✅ **Test individual methods** in isolation +- ✅ **Cover success and error cases** +- ✅ **Fast execution** (no real AWS calls) + +### Integration Tests +- ✅ **Use real AWS clients** and services +- ✅ **Test complete workflows** end-to-end +- ✅ **Require AWS credentials** and permissions +- ✅ **Include cleanup logic** to avoid resource leaks + +### Scenario Tests +- ✅ **Test complete scenarios** with mocked user input +- ✅ **Verify console output** and user interactions +- ✅ **Test multiple user paths** (existing resources, new resources) +- ✅ **Integration test category** (requires real AWS) + +## Common Test Failures to Avoid +- ❌ Using incomplete AWS data structures in mocks +- ❌ Missing test tags for integration tests +- ❌ Not handling cleanup in integration tests +- ❌ Forgetting to set AWS region in test clients +- ❌ Not testing all error conditions from specification +- ❌ Not mocking user inputs in scenario tests +- ❌ Missing Maven test configuration +- ❌ Not using JUnit 5 annotations properly \ No newline at end of file diff --git a/steering_docs/javascript-tech.md b/steering_docs/javascript-tech.md new file mode 100644 index 00000000000..df3e5152416 --- /dev/null +++ b/steering_docs/javascript-tech.md @@ -0,0 +1,188 @@ +# JavaScript Technology Stack & Build System + +## JavaScript/Node.js Development Environment + +### Build Tools & Dependencies +- **Runtime**: Node.js (LTS version recommended) +- **Package Manager**: npm +- **Testing Framework**: Jest +- **Code Formatting**: Prettier +- **Linting**: Biome (or ESLint) +- **SDK Version**: AWS SDK for JavaScript v3 + +### Common Build Commands + +```bash +# Dependencies +npm install # Install dependencies +npm ci # Clean install from package-lock.json + +# Testing +npm test # Run all tests +npm run test:unit # Run unit tests +npm run test:integration # Run integration tests + +# Code Quality +npm run lint # Lint code +npm run format # Format code with Prettier + +# Execution +node src/hello-{service}.js # Run hello scenario +npm start # Run main application +``` + +### JavaScript-Specific Pattern Requirements + +#### File Naming Conventions +- Use kebab-case for file names +- Service prefix pattern: `{service}-action.js` (e.g., `s3-list-buckets.js`) +- Hello scenarios: `hello-{service}.js` (e.g., `hello-s3.js`) +- Test files: `{service}-action.test.js` + +#### Hello Scenario Structure +- **File naming**: `hello-{service}.js` or hello function in main module +- **Function structure**: Async function as main entry point +- **Documentation**: Include JSDoc comments explaining the hello example purpose + +#### Code Structure Standards +- **Module system**: Use ES6 modules (import/export) or CommonJS (require/module.exports) +- **Function naming**: Use camelCase for function names +- **Constants**: Use UPPER_SNAKE_CASE for constants +- **Classes**: Use PascalCase for class names +- **Async/Await**: Use async/await for asynchronous operations + +#### Error Handling Patterns +```javascript +import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3"; + +const client = new S3Client({ region: "us-east-1" }); + +async function listBuckets() { + try { + const command = new ListBucketsCommand({}); + const response = await client.send(command); + + console.log("Buckets:", response.Buckets); + return response.Buckets; + } catch (error) { + if (error.name === "NoSuchBucket") { + console.error("Bucket not found:", error.message); + } else if (error.name === "AccessDenied") { + console.error("Access denied:", error.message); + } else { + console.error("AWS SDK Error:", error.message); + } + throw error; + } +} + +export { listBuckets }; +``` + +#### Testing Standards +- **Test framework**: Use Jest with appropriate matchers +- **Integration tests**: Mark with appropriate test descriptions +- **Async testing**: Use async/await in test functions +- **Mocking**: Use Jest mocks for unit tests when appropriate +- **Test naming**: Use descriptive test names explaining test purpose + +#### Project Structure +``` +src/ +├── hello-{service}.js +├── {service}-actions.js +├── {service}-scenarios.js +└── tests/ + ├── {service}-actions.test.js + └── {service}-integration.test.js +``` + +#### Package.json Configuration +```json +{ + "name": "{service}-examples", + "version": "1.0.0", + "type": "module", + "scripts": { + "test": "jest", + "test:unit": "jest --testPathPattern=unit", + "test:integration": "jest --testPathPattern=integration", + "lint": "biome check .", + "format": "prettier --write ." + }, + "dependencies": { + "@aws-sdk/client-{service}": "^3.0.0", + "@aws-sdk/credential-providers": "^3.0.0" + }, + "devDependencies": { + "jest": "^29.0.0", + "prettier": "^3.0.0", + "@biomejs/biome": "^1.0.0" + } +} +``` + +#### Documentation Requirements +- **JSDoc comments**: Use `/**` for function and class documentation +- **Parameter documentation**: Document parameters with `@param` +- **Return documentation**: Document return values with `@returns` +- **Example documentation**: Include `@example` blocks +- **README sections**: Include npm setup and execution instructions + +### AWS SDK v3 Specific Patterns + +#### Client Configuration +```javascript +import { S3Client } from "@aws-sdk/client-s3"; +import { fromEnv } from "@aws-sdk/credential-providers"; + +const client = new S3Client({ + region: process.env.AWS_REGION || "us-east-1", + credentials: fromEnv(), // Optional: explicit credential provider +}); +``` + +#### Command Pattern Usage +```javascript +import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; + +const client = new S3Client({ region: "us-east-1" }); + +async function uploadObject(bucketName, key, body) { + const command = new PutObjectCommand({ + Bucket: bucketName, + Key: key, + Body: body, + }); + + return await client.send(command); +} +``` + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER use snake_case for JavaScript identifiers** +- ❌ **NEVER forget to handle Promise rejections** +- ❌ **NEVER mix callback and Promise patterns** +- ❌ **NEVER ignore proper error handling for AWS operations** +- ❌ **NEVER skip npm dependency management** + +### Best Practices +- ✅ **ALWAYS use kebab-case for file names** +- ✅ **ALWAYS use camelCase for JavaScript identifiers** +- ✅ **ALWAYS use async/await for asynchronous operations** +- ✅ **ALWAYS include proper error handling for AWS service calls** +- ✅ **ALWAYS use AWS SDK v3 command pattern** +- ✅ **ALWAYS include comprehensive JSDoc documentation** +- ✅ **ALWAYS handle environment variables for configuration** + +### Environment Configuration +- **AWS Region**: Use `AWS_REGION` environment variable +- **Credentials**: Support AWS credential chain (environment, profile, IAM roles) +- **Configuration**: Use environment variables for service-specific settings + +### Integration with Knowledge Base +Before creating JavaScript code examples: +1. Query `coding-standards-KB` for "JavaScript-code-example-standards" +2. Query `JavaScript-premium-KB` for "JavaScript implementation patterns" +3. Follow KB-documented patterns for project structure and module organization +4. Validate against existing JavaScript examples only after KB consultation \ No newline at end of file diff --git a/steering_docs/kotlin-tech.md b/steering_docs/kotlin-tech.md new file mode 100644 index 00000000000..6f90649bfdb --- /dev/null +++ b/steering_docs/kotlin-tech.md @@ -0,0 +1,156 @@ +# Kotlin Technology Stack & Build System + +## Kotlin Development Environment + +### Build Tools & Dependencies +- **Build System**: Gradle +- **Testing Framework**: JUnit 5 +- **Build Plugin**: shadow +- **SDK Version**: AWS SDK for Kotlin v1 +- **Kotlin Version**: 1.5.31 + + +### Common Build Commands + +```bash +# Build and Package +./gradlew compileKotlin # Compile source code +./gradlew build # Build with dependencies +./gradlew clean build # Clean and build + +# Testing +./gradlew test # Run all tests +./gradlew test --tests ClassName # Run specific test class +./gradlew test --tests ClassName.methodName # Run specific test method + +# Execution +./gradlew run + +``` + +### Koltin-Specific Pattern Requirements + +#### File Naming Conventions +- Use PascalCase for class names +- Service prefix pattern: `{Service}Action.kt` (e.g., `S3ListBuckets.kt`) +- Hello scenarios: `Hello{Service}.kt` (e.g., `HelloS3.kt`) +- Test files: `{Service}ActionTest.kt` + +#### Hello Scenario Structure +- **Class naming**: `Hello{Service}.kt` class with main method with no class declaration +- **Method structure**: suspend main method as entry point. All methods need to be suspend. +- **Documentation**: Include comments explaining the purpose of the method. + +#### Code Structure Standards +- **Package naming**: Use reverse domain notation (e.g., `com.example.s3`) +- **Class structure**: One kotlin file matching filename +- **Method naming**: Use camelCase for method names +- **Constants**: Use UPPER_SNAKE_CASE for static final variables +- **Imports**: Group imports logically (Kotlin standard, AWS SDK, other libraries) + +#### Error Handling Patterns + +In Kotlin, suspend functions are designed to be used with coroutines, which provide a way to write asynchronous code that is easy to read and maintain. When it comes to error handling in coroutines, you typically use structured concurrency and the try-catch. + +```java +suspend fun listBucketObjects(bucketName: String) { + try { + val request = ListObjectsRequest { + bucket = bucketName + } + + S3Client.fromEnvironment { region = "us-east-1" }.use { s3 -> + try { + val response = s3.listObjects(request) + response.contents?.forEach { myObject -> + println("The name of the key is ${myObject.key}") + println("The object is ${myObject.size?.let { calKb(it) }} KBs") + println("The owner is ${myObject.owner}") + } + } catch (e: AwsServiceException) { + println("Service error: ${e.statusCode}, ${e.message}") + } catch (e: SdkClientException) { + println("Client error: ${e.message}") + } + } + } catch (e: Exception) { + println("Unexpected error: ${e.message}") + } +} + + +``` + + +#### Testing Standards +- **Test framework**: Use JUnit 5 annotations (`@Test`, `@BeforeEach`, `@AfterEach`) +- **Integration tests**: Mark with `@Tag("IntegrationTest")` +- **Resource management**: Use try-with-resources for AWS clients +- **Assertions**: Use JUnit 5 assertion methods +- **Test naming**: Use descriptive method names explaining test purpose + + +#### Gradle Project Structure for Kotlin +``` +├── build.gradle.kts +├── settings.gradle.kts +├── src/ +│ ├── main/ +│ │ ├── kotlin/ +│ │ │ └── com/ +│ │ │ └── example/ +│ │ │ └── {service}/ +│ │ │ ├── Hello{Service}.kt +│ │ │ ├── {Service}Actions.kt +│ │ │ └── {Service}Scenario.kt +│ │ └── resources/ +│ └── test/ +│ ├── kotlin/ +│ │ └── com/ +│ │ └── example/ +│ │ └── {service}/ +│ │ └── {Service}Test.kt +│ └── resources/ +├── gradle/ +│ └── wrapper/ +│ ├── gradle-wrapper.jar +│ └── gradle-wrapper.properties +└── gradlew +└── gradlew.bat +``` + +#### Documentation Requirements +- **Class Javadoc**: Include purpose, usage examples, and prerequisites +- **Method Javadoc**: Document parameters, return values, and exceptions +- **Inline comments**: Explain complex AWS service interactions +- **README sections**: Include Gradle setup and execution instructions + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER assume class naming without checking existing examples** +- ❌ **NEVER use snake_case for Kotlin class or method names** +- ❌ **NEVER forget to close AWS clients (use .fromEnvironment)** +- ❌ **NEVER ignore proper exception handling for AWS operations** +- ❌ **NEVER skip Gradle dependency management** + +### Best Practices +- ✅ **ALWAYS follow the established Gradle project structure** +- ✅ **ALWAYS use PascalCase for class names and camelCase for methods** +- ✅ **ALWAYS use .fromEnvironment for AWS client management** +- ✅ **ALWAYS include proper exception handling for AWS service calls** +- ✅ **ALWAYS follow Kotlin naming conventions and package structure** +- ✅ **ALWAYS include comprehensive Javadoc documentation** + + + +### Maven Configuration Requirements +- **AWS SDK BOM**: Include AWS SDK Bill of Materials for version management +- **Compiler plugin**: Configure for appropriate Java version +- **Shade plugin**: For creating executable JARs with dependencies +- **Surefire plugin**: Gradle uses the test task for running tests. + +### Integration with Knowledge Base +Before creating Kotlin code examples: +1. Query `coding-standards-KB` for "Kotlin-code-example-standards" +2. Query `Kotlin-premium-KB` for "Kotlin implementation patterns" +3. Follow KB-documented patterns for Gradle structure and class organization +4. Validate against existing Kotlin examples only after KB consultation \ No newline at end of file diff --git a/steering_docs/kotlin-tech/actions.md b/steering_docs/kotlin-tech/actions.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/steering_docs/kotlin-tech/basics.md b/steering_docs/kotlin-tech/basics.md new file mode 100644 index 00000000000..f4c874bb231 --- /dev/null +++ b/steering_docs/kotlin-tech/basics.md @@ -0,0 +1,434 @@ +# Kotlin Interactive Scenario Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Kotlin-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Kotlin-premium-KB", "Kotlin implementation patterns structure") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate interactive scenarios that demonstrate complete workflows using multiple service operations in a guided, educational manner. Implementation must be based on the service SPECIFICATION.md file. + +## Requirements +- **Specification-Driven**: MUST read the `scenarios/basics/{service}/SPECIFICATION.md` +- **Interactive**: USE readLine() for user input and guidance +- **Educational**: Break complex workflows into logical phases +- **Comprehensive**: Cover setup, demonstration, examination, and cleanup +- **Error Handling**: Graceful error handling with user-friendly messages +- **Actions Classes**: MUST use service actions classes for all operations +- **Suspend Functions**: Use coroutines for all AWS operations + +## File Structure +``` +kotlin/services/{service}/ +├── src/main/kotlin/com/kotlin/{service}/ +│ ├── {Service}Scenario.kt # Main scenario file +│ └── {Service}Actions.kt # Actions class (if not exists) +``` + +## MANDATORY Pre-Implementation Steps + +### Step 1: Read Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first to understand: +- **API Actions Used**: Exact operations to implement +- **Proposed Example Structure**: Setup, demonstration, examination, cleanup phases +- **Error Handling**: Specific error codes and handling requirements +- **Scenario Flow**: Step-by-Step workflow description + +### Step 2: Extract Implementation Requirements +From the specification, identify: +- **Setup Phase**: What resources need to be created/configured +- **Demonstration Phase**: What operations to demonstrate +- **Examination Phase**: What data to display and how to filter/analyze +- **Cleanup Phase**: What resources to clean up and user options + +## Scenario Class Pattern +### Implementation Pattern Based on SPECIFICATION.md +```kotlin +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.kotlin.{service} + +import aws.sdk.kotlin.services.{service}.{Service}Client +import aws.sdk.kotlin.services.{service}.model.* +import aws.smithy.kotlin.runtime.ClientException +import kotlinx.coroutines.delay + +/** + * Before running this Kotlin code example, set up your development environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html + * + * This Kotlin code example performs the following tasks: + * + * 1. {Phase 1 description} + * 2. {Phase 2 description} + * 3. {Phase 3 description} + * 4. {Phase 4 description} + */ + +// snippet-start:[{service}.kotlin.{service}_scenario.main] +class {Service}Scenario { + companion object { + private const val DASHES = "".padEnd(80, '-') + private val {service}Actions = {Service}Actions() + private var resourceId: String? = null + + @JvmStatic + suspend fun main(args: Array) { + val usage = """ + Usage: + + + Where: + region - The AWS region (for example, us-east-1). + """.trimIndent() + + if (args.size != 1) { + println(usage) + return + } + + val region = args[0] + + {Service}Client { this.region = region }.use { {service}Client -> + println(DASHES) + println("Welcome to the {AWS Service} basics scenario!") + println(DASHES) + println(""" + {Service description and what users will learn} + """.trimIndent()) + + try { + runScenario({service}Client) + } catch (e: Exception) { + println("❌ Scenario failed: ${e.message}") + e.printStackTrace() + } finally { + cleanupPhase({service}Client) + } + } + } + + private suspend fun runScenario({service}Client: {Service}Client) { + try { + setupPhase({service}Client) + demonstrationPhase({service}Client) + examinationPhase({service}Client) + } catch (e: Exception) { + println("❌ Error during scenario execution: ${e.message}") + throw e + } + } + + private suspend fun setupPhase({service}Client: {Service}Client) { + println(DASHES) + println("Setting up {AWS Service}...") + println(DASHES) + + try { + // Example: Check for existing resources (from specification) + val existingResources = {service}Actions.listResources({service}Client) + if (existingResources.isNotEmpty()) { + println("Found ${existingResources.size} existing resource(s):") + existingResources.forEach { resource -> + println(" - ${resource.{resourceName}}") + } + + print("Would you like to use an existing resource? (y/n): ") + val useExisting = readLine()?.lowercase()?.startsWith("y") ?: false + if (useExisting) { + resourceId = existingResources.first().{resourceId} + return + } + } + + // Create new resource as specified + println("Creating new resource...") + resourceId = {service}Actions.createResource({service}Client) + println("✅ Resource created successfully: $resourceId") + + } catch (e: {Service}Exception) { + println("❌ Error during setup: ${e.message}") + throw e + } + } + + private suspend fun demonstrationPhase({service}Client: {Service}Client) { + println(DASHES) + println("Demonstrating {AWS Service} capabilities...") + println(DASHES) + + try { + // Implement specific operations from specification + // Example: Generate sample data if specified + resourceId?.let { id -> + {service}Actions.createSampleData({service}Client, id) + println("✅ Sample data created successfully") + + // Wait if specified in the specification + println("Waiting for data to be processed...") + delay(5000) + } + + } catch (e: {Service}Exception) { + println("❌ Error during demonstration: ${e.message}") + throw e + } + } + + private suspend fun examinationPhase({service}Client: {Service}Client) { + println(DASHES) + println("Examining {AWS Service} data...") + println(DASHES) + + try { + resourceId?.let { id -> + // List and examine data as specified + val dataItems = {service}Actions.listData({service}Client, id) + if (dataItems.isEmpty()) { + println("No data found. Data may take a few minutes to appear.") + return + } + + println("Found ${dataItems.size} data item(s)") + + // Get detailed information as specified + val detailedData = {service}Actions.getDataDetails( + {service}Client, + id, + dataItems.take(5) + ) + displayDataSummary(detailedData) + + // Show detailed view if specified + if (detailedData.isNotEmpty()) { + print("Would you like to see detailed information? (y/n): ") + val showDetails = readLine()?.lowercase()?.startsWith("y") ?: false + if (showDetails) { + displayDataDetails(detailedData.first()) + } + } + + // Filter data as specified + filterDataByCriteria(dataItems) + } + + } catch (e: {Service}Exception) { + println("❌ Error during examination: ${e.message}") + throw e + } + } + + private suspend fun cleanupPhase({service}Client: {Service}Client) { + resourceId?.let { id -> + println(DASHES) + println("Cleanup options:") + println("Note: Deleting the resource will stop all monitoring/processing.") + println(DASHES) + + print("Would you like to delete the resource? (y/n): ") + val deleteResource = readLine()?.lowercase()?.startsWith("y") ?: false + + if (deleteResource) { + try { + {service}Actions.deleteResource({service}Client, id) + println("✅ Deleted resource: $id") + } catch (e: {Service}Exception) { + println("❌ Error deleting resource: ${e.message}") + } + } else { + println("Resource $id will continue running.") + println("You can manage it through the AWS Console or delete it later.") + } + } + } + + private fun displayDataSummary(detailedData: List<{DetailedData}>) { + println("\nData Summary:") + detailedData.forEach { data -> + println(" • ${data.{summaryField}}") + } + } + + private fun displayDataDetails(data: {DetailedData}) { + println("\nDetailed Information:") + println(" ID: ${data.{idField}}") + println(" Status: ${data.{statusField}}") + println(" Created: ${data.{createdField}}") + // Add more fields as specified + } + + private fun filterDataByCriteria(dataItems: List<{DataItem}>) { + println("\nFiltering data by criteria...") + // Implement filtering logic as specified in the specification + } + } +} +// snippet-end:[{service}.kotlin.{service}_scenario.main] +``` + +## Scenario Phase Structure (Based on Specification) + +### Setup Phase +- **Read specification Setup section** for exact requirements +- Check for existing resources as specified +- Create necessary resources using actions methods +- Configure service settings per specification +- Verify setup completion as described + +### Demonstration Phase +- **Follow specification Demonstration section** exactly +- Perform core service operations using actions methods +- Generate sample data if specified in the specification +- Show service capabilities as outlined +- Provide educational context from specification + +### Examination Phase +- **Implement specification Examination section** requirements +- List and examine results using actions methods +- Filter and analyze data as specified +- Display detailed information per specification format +- Allow user interaction as described in specification + +### Cleanup Phase +- **Follow specification Cleanup section** guidance +- Offer cleanup options with warnings from specification +- Handle cleanup errors gracefully using actions methods +- Provide alternative management options as specified +- Confirm completion per specification + +## User Interaction Patterns + +### Input Types +```kotlin +// Yes/No questions +print("Use existing resource? (y/n): ") +val useExisting = readLine()?.lowercase()?.startsWith("y") ?: false + +// Text input +print("Enter resource name: ") +val resourceName = readLine() ?: "" + +// Numeric input +print("How many items? ") +val count = readLine()?.toIntOrNull() ?: 0 +``` + +### Information Display +```kotlin +// Progress indicators +println("✅ Operation completed successfully") +println("⚠️ Warning message") +println("❌ Error occurred") + +// Formatted output +println(DASHES) +println("Found ${items.size} items:") +items.forEach { item -> + println(" • ${item.name}") +} +``` + +## Specification-Based Error Handling + +### Error Handling from Specification +The specification includes an "Errors" section with specific error codes and handling: + +```kotlin +// Example error handling based on specification +try { + val response = {service}Actions.createResource({service}Client) + return response +} catch (e: {Service}Exception) { + when (e.errorDetails?.errorCode) { + "BadRequestException" -> { + // Handle as specified: "Validate input parameters and notify user" + println("❌ Invalid configuration. Please check your parameters.") + } + "InternalServerErrorException" -> { + // Handle as specified: "Retry operation with exponential backoff" + println("⚠️ Service temporarily unavailable. Retrying...") + // Implement retry logic + } + else -> { + println("❌ Unexpected error: ${e.message}") + } + } + throw e +} catch (e: ClientException) { + println("❌ Client error: ${e.message}") + throw e +} +``` + +## Scenario Requirements +- ✅ **ALWAYS** read and implement based on `scenarios/basics/{service}/SPECIFICATION.md` +- ✅ **ALWAYS** include descriptive comment block at top explaining scenario steps from specification +- ✅ **ALWAYS** use readLine() for user interaction +- ✅ **ALWAYS** use service actions classes for all AWS operations +- ✅ **ALWAYS** implement proper cleanup in finally block +- ✅ **ALWAYS** break scenario into logical phases per specification +- ✅ **ALWAYS** include error handling per specification's Errors section +- ✅ **ALWAYS** provide educational context and explanations from specification +- ✅ **ALWAYS** handle edge cases (no resources found, etc.) as specified +- ✅ **ALWAYS** use suspend functions for AWS operations +- ✅ **ALWAYS** use coroutines properly with delay() instead of Thread.sleep() + +## Implementation Workflow + +### Step-by-Step Implementation Process +1. **Read Specification**: Study `scenarios/basics/{service}/SPECIFICATION.md` thoroughly +2. **Extract API Actions**: Note all API actions listed in "API Actions Used" section +3. **Map to Actions Methods**: Ensure actions class has methods for all required actions +4. **Implement Phases**: Follow the "Proposed example structure" section exactly +5. **Add Error Handling**: Implement error handling per the "Errors" section +6. **Test Against Specification**: Verify implementation matches specification requirements + +### Specification Sections to Implement +- **API Actions Used**: All operations must be available in actions class +- **Proposed example structure**: Direct mapping to scenario phases +- **Setup**: Exact setup steps and resource creation +- **Demonstration**: Specific operations to demonstrate +- **Examination**: Data analysis and filtering requirements +- **Cleanup**: Resource cleanup options and user choices +- **Errors**: Specific error codes and handling strategies + +## Error Handling in Scenarios +- **Follow specification error table**: Implement exact error handling per specification +- Catch and display user-friendly error messages per specification guidance +- Continue scenario execution when possible as specified +- Provide guidance on resolving issues from specification +- Ensure cleanup runs even if errors occur + +## Educational Elements +- **Use specification descriptions**: Explain operations using specification language +- Show before/after states as outlined in specification +- Provide context about service capabilities from specification +- Include tips and best practices mentioned in specification +- Follow the educational flow described in specification structure + +## Kotlin-Specific Features +- **Coroutines**: Use suspend functions and proper coroutine handling +- **Null Safety**: Leverage Kotlin's null safety features +- **Extension Functions**: Use where appropriate for cleaner code +- **Data Classes**: Use for structured data representation +- **Smart Casts**: Leverage Kotlin's smart casting capabilities +- **String Templates**: Use for cleaner string formatting \ No newline at end of file diff --git a/steering_docs/kotlin-tech/hello.md b/steering_docs/kotlin-tech/hello.md new file mode 100644 index 00000000000..cd09f170c97 --- /dev/null +++ b/steering_docs/kotlin-tech/hello.md @@ -0,0 +1,311 @@ +# Kotlin Hello Examples Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Kotlin-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Kotlin-premium-KB", "Kotlin implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate simple "Hello" examples that demonstrate basic service connectivity and the most fundamental operation using direct AWS SDK for Kotlin client calls. + +## Requirements +- **MANDATORY**: Every AWS service MUST include a "Hello" scenario +- **Simplicity**: Should be the most basic, minimal example possible +- **Standalone**: Must work independently of other examples +- **Direct Client**: Use AWS SDK client directly, no actions classes needed +- **Suspend Functions**: Use coroutines for all AWS operations + +## File Structure +``` +kotlin/services/{service}/ +├── src/main/kotlin/com/kotlin/{service}/ +│ └── Hello{Service}.kt # Hello example file +``` + +## Hello Example Pattern +```kotlin +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.kotlin.{service} + +import aws.sdk.kotlin.services.{service}.{Service}Client +import aws.sdk.kotlin.services.{service}.model.* +import aws.smithy.kotlin.runtime.ClientException +import kotlin.system.exitProcess + +/** + * Before running this Kotlin code example, set up your development environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/setup.html + * + * This example shows how to get started with {AWS Service} by {basic operation description}. + */ + +// snippet-start:[{service}.kotlin.hello.main] +suspend fun main(args: Array) { + val usage = """ + Usage: + + + Where: + region - The AWS region (for example, us-east-1). + """.trimIndent() + + if (args.size != 1) { + println(usage) + exitProcess(1) + } + + val region = args[0] + hello{Service}(region) +} + +/** + * Invokes a {AWS Service} operation to {basic operation description}. + * + * @param region the AWS region to use for the operation + */ +suspend fun hello{Service}(region: String) { + {Service}Client { this.region = region }.use { {service}Client -> + try { + // Perform the most basic operation for this service + val request = {BasicOperation}Request { + // Add any required parameters + } + + val response = {service}Client.{basicOperation}(request) + + println("🔍 Hello, {AWS Service}!") + + // Display appropriate result information + response.{resultField}?.let { results -> + if (results.isNotEmpty()) { + println("Found ${results.size} {resources}:") + results.forEach { resource -> + println(" - ${resource.{resourceName}}") + } + } else { + println("No {resources} found, but {AWS Service} is available and ready to use.") + } + } ?: run { + println("{AWS Service} is available and ready to use.") + } + + } catch (e: {Service}Exception) { + println("❌ {AWS Service} error occurred: ${e.message}") + when (e.errorDetails?.errorCode) { + "UnauthorizedOperation" -> { + println("💡 You don't have permission to access {AWS Service}.") + println(" Please check your IAM permissions.") + } + "InvalidParameterValue" -> { + println("💡 Invalid parameter provided to {AWS Service}.") + println(" Please check your input parameters.") + } + else -> { + println("💡 Please check your AWS credentials and region configuration.") + } + } + exitProcess(1) + } catch (e: ClientException) { + println("❌ Client error occurred: ${e.message}") + println("💡 Please check your AWS credentials and network connectivity.") + exitProcess(1) + } + } +} +// snippet-end:[{service}.kotlin.hello.main] +``` + +## Hello Examples by Service Type + +### List-Based Services (S3, DynamoDB, etc.) +- **Operation**: List primary resources (buckets, tables, etc.) +- **Message**: Show count and names of resources + +### Status-Based Services (GuardDuty, Config, etc.) +- **Operation**: Check service status or list detectors/configurations +- **Message**: Show service availability and basic status + +### Compute Services (EC2, Lambda, etc.) +- **Operation**: List instances/functions or describe regions +- **Message**: Show available resources or regions + +## Service-Specific Hello Examples + +### For Services with List Operations +```kotlin +suspend fun hello{Service}(region: String) { + {Service}Client { this.region = region }.use { {service}Client -> + try { + val request = List{Resources}Request { } + val response = {service}Client.list{Resources}(request) + + println("🔍 Hello, {AWS Service}!") + + response.{resources}?.let { resources -> + println("Found ${resources.size} {resources}:") + resources.forEach { resource -> + println(" - ${resource.{resourceName}}") + } + } + + } catch (e: {Service}Exception) { + println("❌ {AWS Service} error: ${e.message}") + exitProcess(1) + } + } +} +``` + +### For Services with Status Operations +```kotlin +suspend fun hello{Service}(region: String) { + {Service}Client { this.region = region }.use { {service}Client -> + try { + val request = Get{Service}StatusRequest { } + val response = {service}Client.get{Service}Status(request) + + println("🔍 Hello, {AWS Service}!") + println("Service status: ${response.status}") + println("{AWS Service} is ready to use.") + + } catch (e: {Service}Exception) { + println("❌ {AWS Service} error: ${e.message}") + exitProcess(1) + } + } +} +``` + +### For Services with Describe Operations +```kotlin +suspend fun hello{Service}(region: String) { + {Service}Client { this.region = region }.use { {service}Client -> + try { + val request = Describe{Resources}Request { + maxResults = 10 + } + val response = {service}Client.describe{Resources}(request) + + println("🔍 Hello, {AWS Service}!") + + response.{resources}?.let { resources -> + println("Found ${resources.size} {resources}:") + resources.forEach { resource -> + println(" - ${resource.{resourceId}} (${resource.state})") + } + } + + } catch (e: {Service}Exception) { + println("❌ {AWS Service} error: ${e.message}") + exitProcess(1) + } + } +} +``` + +## Error Handling Requirements + +### Standard Error Handling Pattern +```kotlin +try { + // AWS operation + val response = {service}Client.operation(request) + +} catch (e: {Service}Exception) { + // Service-specific errors + when (e.errorDetails?.errorCode) { + "UnauthorizedOperation" -> { + println("❌ You don't have permission to access {AWS Service}.") + println("💡 Please check your IAM permissions.") + } + "InvalidParameterValue" -> { + println("❌ Invalid parameter provided to {AWS Service}.") + println("💡 Please verify your input parameters.") + } + "ResourceNotFoundException" -> { + println("❌ Resource not found in {AWS Service}.") + println("💡 Please check if the resource exists.") + } + else -> { + println("❌ {AWS Service} error: ${e.message}") + println("💡 Please check your AWS configuration.") + } + } + exitProcess(1) + +} catch (e: ClientException) { + // General client errors (network, credentials, etc.) + println("❌ Client error: ${e.message}") + println("💡 Please check your AWS credentials and network connectivity.") + exitProcess(1) +} +``` + +## Validation Requirements +- ✅ **Must run without errors** (with proper credentials) +- ✅ **Must handle credential issues gracefully** +- ✅ **Must display meaningful output** +- ✅ **Must use direct AWS SDK client calls** +- ✅ **Must include proper snippet tags** +- ✅ **Must accept region as command line argument** +- ✅ **Must close client resources properly** (use .use{}) +- ✅ **Must use suspend functions** for AWS operations +- ✅ **Must use Kotlin idioms** (null safety, string templates, etc.) + +## Common Patterns +- Always use `{Service}Client { this.region = region }.use { }` for client creation and resource management +- Include comprehensive error handling for both service and client exceptions +- Provide user-friendly output messages with emojis for better UX +- Handle command line arguments properly with usage messages +- Use Kotlin's null safety features (`?.let`, `?:`) +- Keep it as simple as possible - no additional classes or complexity +- Use proper Kotlin naming conventions (camelCase for functions, PascalCase for classes) +- Use string templates for cleaner output formatting + +## Build Configuration +Ensure the service dependency is included in `build.gradle.kts`: + +```kotlin +dependencies { + implementation("aws.sdk.kotlin:aws-core:+") + implementation("aws.sdk.kotlin:{service}:+") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") +} +``` + +## Testing Requirements +- ✅ **Must compile without errors** +- ✅ **Must run with valid AWS credentials** +- ✅ **Must handle invalid regions gracefully** +- ✅ **Must display appropriate output for empty results** +- ✅ **Must exit cleanly on errors** +- ✅ **Must properly handle coroutines** + +## Kotlin-Specific Features +- **Coroutines**: Use suspend functions for all AWS operations +- **Null Safety**: Leverage `?.let` and `?:` operators +- **String Templates**: Use `${}` for variable interpolation +- **Extension Functions**: Use `.use{}` for resource management +- **Data Classes**: Use for structured responses when needed +- **Smart Casts**: Leverage Kotlin's type inference +- **Trailing Lambdas**: Use DSL-style builders for requests \ No newline at end of file diff --git a/steering_docs/kotlin-tech/metadata.md b/steering_docs/kotlin-tech/metadata.md new file mode 100644 index 00000000000..13e790e3ec5 --- /dev/null +++ b/steering_docs/kotlin-tech/metadata.md @@ -0,0 +1,256 @@ +# Kotlin Metadata Generation + +## Purpose +Generate documentation metadata files that integrate with AWS Documentation pipeline for snippet extraction and cross-referencing. + +## Requirements +- **Specification First**: Always check service specification for exact metadata keys +- **Snippet Tags**: Match snippet tags in code exactly +- **Complete Coverage**: Include all actions and scenarios from specification + +## File Structure +``` +.doc_gen/metadata/ +├── {service}_metadata.yaml # Service metadata file +``` + +## Metadata Discovery Process + +### Step 1: Check Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first for metadata requirements. + +Look for the metadata table: +```markdown +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`CreateDetector` |{service}_metadata.yaml |{service}_CreateDetector | +|`GetDetector` |{service}_metadata.yaml |{service}_GetDetector | +|`Service Basics Scenario` |{service}_metadata.yaml |{service}_Scenario | +``` + +### Step 2: Use Exact Metadata Keys +**NEVER** create custom metadata keys when specification defines them. Use the exact keys from the specification table. + +## Metadata File Pattern +```yaml +# .doc_gen/metadata/{service}_metadata.yaml + +{service}_CreateResource: + title: Create a &{ServiceAbbrev}; resource + title_abbrev: Create a resource + synopsis: create a &{ServiceAbbrev}; resource. + category: Actions + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.kotlin.create_resource.main + services: + {service}: {CreateResource} + +{service}_GetResource: + title: Get a &{ServiceAbbrev}; resource + title_abbrev: Get a resource + synopsis: get a &{ServiceAbbrev}; resource. + category: Actions + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.kotlin.get_resource.main + services: + {service}: {GetResource} + +{service}_Scenario: + title: Get started with &{ServiceAbbrev}; resources + title_abbrev: Get started with resources + synopsis: learn the basics of &{ServiceAbbrev}; by creating resources and managing them. + category: Scenarios + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/{service} + sdkguide: + excerpts: + - description: Create a {Service} actions class to manage operations. + snippet_tags: + - {service}.kotlin.{service}_actions.main + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - {service}.kotlin.{service}_scenario.main + services: + {service}: {CreateResource, GetResource, ListResources, DeleteResource} + +{service}_Hello: + title: Hello &{ServiceAbbrev}; + title_abbrev: Hello &{ServiceAbbrev}; + synopsis: get started using &{ServiceAbbrev};. + category: Hello + languages: + Kotlin: + versions: + - sdk_version: 1 + github: kotlin/services/{service} + sdkguide: + excerpts: + - description: + snippet_tags: + - {service}.kotlin.hello.main + services: + {service}: {ListResources} +``` + +## Snippet Tag Requirements + +### Code Snippet Tags +All code must include proper snippet tags that match metadata: + +```kotlin +// snippet-start:[{service}.kotlin.{action_name}.main] +suspend fun {actionMethod}({service}Client: {Service}Client, param: String): {ActionName}Response { + // Action implementation +} +// snippet-end:[{service}.kotlin.{action_name}.main] +``` + +### Actions Class Tags +```kotlin +// snippet-start:[{service}.kotlin.{service}_actions.main] +class {Service}Actions { + // Actions class implementation +} +// snippet-end:[{service}.kotlin.{service}_actions.main] +``` + +### Scenario Tags +```kotlin +// snippet-start:[{service}.kotlin.{service}_scenario.main] +class {Service}Scenario { + // Scenario class implementation +} +// snippet-end:[{service}.kotlin.{service}_scenario.main] +``` + +### Hello Tags +```kotlin +// snippet-start:[{service}.kotlin.hello.main] +suspend fun main() { + // Hello implementation +} +// snippet-end:[{service}.kotlin.hello.main] +``` + +## Service Abbreviations + +Common service abbreviations for metadata: +- **GuardDuty**: GD +- **DynamoDB**: DDB +- **Simple Storage Service**: S3 +- **Elastic Compute Cloud**: EC2 +- **Identity and Access Management**: IAM +- **Key Management Service**: KMS +- **Simple Notification Service**: SNS +- **Simple Queue Service**: SQS +- **Inspector**: Inspector + +## Metadata Categories + +### Actions +Individual service operations (CreateResource, GetResource, etc.) + +### Scenarios +Multi-step workflows demonstrating service usage + +### Hello +Simple introduction examples + +### Cross-service +Examples spanning multiple AWS services + +## Kotlin-Specific Metadata Fields + +### SDK Version +Always use `sdk_version: 1` for Kotlin SDK examples + +### GitHub Path +Use `kotlin/services/{service}` for Kotlin examples + +### SDK Guide +Include `sdkguide:` field when documentation links are available + +### Snippet Tag Format +Use format: `{service}.kotlin.{operation}.main` + +## Metadata Validation + +### Required Fields +- ✅ **title**: Descriptive title with service abbreviation +- ✅ **title_abbrev**: Shortened title +- ✅ **synopsis**: Brief description of what the example does +- ✅ **category**: Actions, Scenarios, Hello, or Cross-service +- ✅ **languages.Kotlin.versions**: SDK version information +- ✅ **github**: Path to example code +- ✅ **snippet_tags**: Matching tags from code +- ✅ **services**: Service operations used + +### Validation Commands +```bash +# Validate metadata with writeme tool +cd .tools/readmes +python -m writeme --languages Kotlin:1 --services {service} +``` + +## Common Metadata Errors +- ❌ **Custom metadata keys** when specification exists +- ❌ **Mismatched snippet tags** between code and metadata +- ❌ **Missing service operations** in services section +- ❌ **Incorrect github paths** to example code +- ❌ **Wrong service abbreviations** in titles +- ❌ **Missing required fields** in metadata structure +- ❌ **Wrong SDK version** (should be 1 for Kotlin) + +## Metadata Generation Workflow +1. **Read specification** for exact metadata requirements +2. **Extract metadata table** from specification +3. **Create metadata file** using specification keys +4. **Add snippet tags** to all code files +5. **Validate metadata** with writeme tool +6. **Fix any validation errors** before completion + +## Kotlin-Specific Considerations + +### Package Structure +Kotlin examples are organized in packages: +``` +kotlin/services/{service}/src/main/kotlin/com/kotlin/{service}/ +``` + +### File Naming +- Hello examples: `Hello{Service}.kt` +- Actions classes: `{Service}Actions.kt` +- Scenarios: `{Service}Basics.kt` or `{Service}Scenario.kt` + +### Multiple Excerpts +For complex examples, use multiple excerpts: +```yaml +excerpts: + - description: Create a {Service} actions class to manage operations. + snippet_tags: + - {service}.kotlin.{service}_actions.main + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - {service}.kotlin.{service}_scenario.main +``` diff --git a/steering_docs/kotlin-tech/orchestration.md b/steering_docs/kotlin-tech/orchestration.md new file mode 100644 index 00000000000..33dcd816f9c --- /dev/null +++ b/steering_docs/kotlin-tech/orchestration.md @@ -0,0 +1,407 @@ +# Kotlin Code Generation Orchestration + +## Purpose +Coordinate the modular components to generate complete AWS SDK for Kotlin code examples. Each component can be used independently or in sequence. + +## Component Dependencies + +```mermaid +graph TD + A[Knowledge Base Consultation] --> B[Hello Example] + A --> C[Actions Class] + A --> D[Scenario] + + C --> E[Tests - Unit Tests] + E --> F[Tests - Integration Tests] + E --> G[Tests - Scenario Tests] + + B --> H[Metadata Generation] + C --> H + D --> H + + H --> I[README Generation] + + J[Service Specification] --> H + J --> C + J --> D +``` + +## Execution Workflows + +### Full Service Implementation +Complete implementation of a new AWS service: + +```bash +# 1. Knowledge Base Consultation (MANDATORY FIRST) +# Use ListKnowledgeBases + QueryKnowledgeBases for standards and patterns + +# 2. Generate Core Components +# - Hello example: Hello{Service}.kt +# - Actions class: {Service}Actions.kt +# - Scenario: {Service}Basics.kt or {Service}Scenario.kt +# - Build configuration: build.gradle.kts updates + +# 3. Generate Test Suite +# - Unit tests: {Service}ActionsTest.kt +# - Integration tests: {Service}IntegrationTest.kt +# - Scenario tests: {Service}ScenarioTest.kt + +# 4. Generate Metadata +# - Read service specification for exact metadata keys +# - Create .doc_gen/metadata/{service}_metadata.yaml + +# 5. Generate Documentation +# - Run writeme tool to create/update README.md +``` + +### Individual Component Updates + +#### Update Hello Example Only +```bash +# Focus: hello.md guidance +# Files: Hello{Service}.kt +# Validation: Compile and run hello example +``` + +#### Update Actions Class Only +```bash +# Focus: actions.md guidance +# Files: {Service}Actions.kt +# Validation: Run unit tests for actions methods +``` + +#### Update Scenario Only +```bash +# Focus: basics.md guidance +# Files: {Service}Basics.kt or {Service}Scenario.kt +# Validation: Run scenario tests, check user interaction +``` + +#### Update Tests Only +```bash +# Focus: tests.md guidance +# Files: All test files in test/ directory +# Validation: Run ./gradlew test with all test categories +``` + +#### Update Metadata Only +```bash +# Focus: metadata.md guidance +# Files: .doc_gen/metadata/{service}_metadata.yaml +# Validation: Run writeme tool validation +``` + +#### Update Documentation Only +```bash +# Focus: readme.md guidance +# Files: README.md (generated) +# Validation: Check README completeness and accuracy +``` + +## Quality Gates + +### Component-Level Validation +Each component has specific validation requirements: + +#### Hello Example Validation +```bash +cd kotlin/services/{service} +./gradlew run --args="us-east-1" +``` + +#### Actions Class Validation +```bash +cd kotlin/services/{service} +./gradlew compileKotlin +# Verify compilation succeeds and no syntax errors +``` + +#### Scenario Validation +```bash +cd kotlin/services/{service} +./gradlew run --args="us-east-1" +``` + +#### Test Validation +```bash +cd kotlin/services/{service} +./gradlew test --tests "*ActionsTest" +./gradlew test --tests "*IntegrationTest" +``` + +#### Code Quality Validation +```bash +cd kotlin/services/{service} +./gradlew ktlintCheck +./gradlew detekt +``` + +#### Documentation Validation +```bash +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Kotlin:1 --services {service} +``` + +### Integration Validation +Full integration testing across all components: + +```bash +# 1. All unit tests pass +cd kotlin/services/{service} +./gradlew test --exclude-task integrationTest + +# 2. All integration tests pass +./gradlew integrationTest + +# 3. All examples execute successfully +./gradlew run --args="us-east-1" + +# 4. Code quality passes +./gradlew ktlintCheck detekt + +# 5. Documentation generates successfully +cd .tools/readmes && source .venv/bin/activate && python -m writeme --languages Kotlin:1 --services {service} +``` + +## Component Selection Guide + +### When to Use Individual Components + +#### Hello Example Only +- Quick service introduction needed +- Testing basic service connectivity +- Creating minimal working example + +#### Actions Class Only +- Need reusable service operations +- Building foundation for other examples +- Focusing on error handling patterns + +#### Scenario Only +- Demonstrating complete workflows +- Educational/tutorial content +- Interactive user experiences + +#### Tests Only +- Improving test coverage +- Adding new test cases +- Fixing test infrastructure + +#### Metadata Only +- Documentation pipeline integration +- Updating snippet references +- Fixing metadata validation errors + +#### Documentation Only +- README updates needed +- Documentation refresh +- Link validation and updates + +### When to Use Full Workflow +- New service implementation +- Complete service overhaul +- Major structural changes +- Initial service setup + +## Error Recovery + +### Component Failure Handling +If any component fails, you can: + +1. **Fix and retry** the specific component +2. **Skip and continue** with other components +3. **Rollback changes** and restart from known good state + +### Common Recovery Scenarios + +#### Compilation Failures +```bash +# Fix compilation issues and re-run +cd kotlin/services/{service} +./gradlew clean compileKotlin +``` + +#### Test Failures +```bash +# Fix test issues and re-run +./gradlew test --tests "FailingTest" --info +``` + +#### Metadata Validation Failures +```bash +# Check metadata syntax +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Validate against specification +# Compare with scenarios/basics/{service}/SPECIFICATION.md +``` + +#### Documentation Generation Failures +```bash +# Check for missing dependencies +cd .tools/readmes && source .venv/bin/activate && pip list + +# Validate metadata first +python -m writeme --languages Kotlin:1 --services {service} --verbose +``` + +## Build System Integration + +### Gradle Configuration +Ensure proper Gradle configuration in `build.gradle.kts`: + +```kotlin +plugins { + kotlin("jvm") version "1.9.10" + application + id("org.jlleitschuh.gradle.ktlint") version "11.6.1" + id("io.gitlab.arturbosch.detekt") version "1.23.1" +} + +dependencies { + implementation("aws.sdk.kotlin:{service}:1.0.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0") + testImplementation("io.mockk:mockk:1.13.8") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") +} + +application { + mainClass.set("com.kotlin.{service}.Hello{Service}Kt") +} + +tasks.test { + useJUnitPlatform() + exclude("**/*IntegrationTest*") +} + +tasks.register("integrationTest") { + useJUnitPlatform() + include("**/*IntegrationTest*") + group = "verification" + description = "Runs integration tests" +} + +ktlint { + version.set("0.50.0") +} + +detekt { + config.setFrom("$projectDir/detekt.yml") + buildUponDefaultConfig = true +} +``` + +### Test Execution Tasks +```kotlin +tasks.register("unitTest") { + useJUnitPlatform() + exclude("**/*IntegrationTest*") + group = "verification" + description = "Runs unit tests" +} + +tasks.register("integrationTest") { + useJUnitPlatform() + include("**/*IntegrationTest*") + group = "verification" + description = "Runs integration tests" +} +``` + +## CI/CD Integration + +### Automated Validation Pipeline +```bash +# In CI/CD pipeline, validate all components +cd kotlin/services/{service} + +# 1. Compile all code +./gradlew compileKotlin compileTestKotlin + +# 2. Run unit tests +./gradlew unitTest + +# 3. Run integration tests (if credentials available) +./gradlew integrationTest + +# 4. Check code quality +./gradlew ktlintCheck detekt + +# 5. Validate documentation +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Kotlin:1 --services {service} --check +``` + +## Kotlin-Specific Considerations + +### Coroutines and Suspend Functions +Kotlin examples use coroutines for async operations: +```kotlin +suspend fun main() { + // Async operations +} + +suspend fun performAction(): Response { + // Suspend function implementation +} +``` + +### Null Safety +Leverage Kotlin's null safety features: +```kotlin +val response: Response? = client.operation() +response?.let { + // Handle non-null response +} +``` + +### Extension Functions +Use extension functions for utility operations: +```kotlin +fun List.filterByStatus(status: Status): List { + return this.filter { it.status == status } +} +``` + +### Data Classes +Use data classes for structured data: +```kotlin +data class ResourceInfo( + val id: String, + val name: String, + val status: Status +) +``` + +## Build Tool Integration + +### Gradle Wrapper +Always use Gradle wrapper for consistency: +```bash +./gradlew build +./gradlew test +./gradlew run +``` + +### Multi-Module Projects +For complex services, consider multi-module structure: +``` +kotlin/services/{service}/ +├── build.gradle.kts +├── actions/ +│ ├── build.gradle.kts +│ └── src/main/kotlin/ +├── scenarios/ +│ ├── build.gradle.kts +│ └── src/main/kotlin/ +└── examples/ + ├── build.gradle.kts + └── src/main/kotlin/ +``` + +This modular approach allows for targeted updates, easier debugging, and more maintainable code generation processes while maintaining Kotlin-specific build and testing requirements. \ No newline at end of file diff --git a/steering_docs/kotlin-tech/readme_writeme.md b/steering_docs/kotlin-tech/readme_writeme.md new file mode 100644 index 00000000000..c3aa49a8ee1 --- /dev/null +++ b/steering_docs/kotlin-tech/readme_writeme.md @@ -0,0 +1,330 @@ +# Kotlin README/WRITEME and Documentation Generation + +## Purpose +Generate and update README files and documentation using the writeme tool to ensure consistency and completeness. + +## Requirements +- **Automated Generation**: Use writeme tool for README generation +- **Metadata Dependency**: Requires complete metadata files +- **Virtual Environment**: Run writeme in isolated environment +- **Validation**: Ensure all documentation is up-to-date + +## File Structure +``` +kotlin/services/{service}/ +├── README.md # Generated service README +├── build.gradle.kts # Gradle dependencies +└── {service}_metadata.yaml # Metadata (in .doc_gen/metadata/) +``` + +## README Generation Process + +### Step 1: Setup Writeme Environment +```bash +cd .tools/readmes + +# Create virtual environment +python -m venv .venv + +# Activate environment (Linux/macOS) +source .venv/bin/activate + +# Activate environment (Windows) +.venv\Scripts\activate + +# Install dependencies +python -m pip install -r requirements_freeze.txt +``` + +### Step 2: Generate README +```bash +# Generate README for specific service +python -m writeme --languages Kotlin:1 --services {service} +``` + +### Step 3: Validate Generation +- ✅ **README.md created/updated** in service directory +- ✅ **No generation errors** in writeme output +- ✅ **All examples listed** in README +- ✅ **Proper formatting** and structure +- ✅ **Working links** to code files + +## README Content Structure + +### Generated README Sections +1. **Service Overview**: Description of AWS service +2. **Code Examples**: List of available examples +3. **Prerequisites**: Setup requirements +4. **Installation**: Dependency installation +5. **Usage**: How to run examples +6. **Tests**: Testing instructions +7. **Additional Resources**: Links to documentation + +### Example README Content +```markdown +# {AWS Service} code examples for the SDK for Kotlin + +## Overview + +This is a workspace where you can find the following AWS SDK for Kotlin +{AWS Service} examples. + +## ⚠ Important + +* Running this code might result in charges to your AWS account. +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. + +## Code examples + +### Actions + +The following examples show you how to perform actions using the AWS SDK for Kotlin. + +* [Create a resource](src/main/kotlin/com/kotlin/{service}/{Service}Actions.kt#L123) (`CreateResource`) +* [Get a resource](src/main/kotlin/com/kotlin/{service}/{Service}Actions.kt#L456) (`GetResource`) + +### Scenarios + +The following examples show you how to implement common scenarios. + +* [Get started with resources](src/main/kotlin/com/kotlin/{service}/{Service}Basics.kt) - Learn the basics by creating and managing resources. + +### Hello + +* [Hello {Service}](src/main/kotlin/com/kotlin/{service}/Hello{Service}.kt) - Get started with {AWS Service}. + +## Prerequisites + +- You must have an AWS account, and have your default credentials and AWS Region configured. +- Kotlin 1.9 or later +- Gradle 8.0 or later + +## Install + +To build and run the examples, navigate to the directory that contains a `build.gradle.kts` file and run the following command: + +``` +./gradlew build +``` + +## Run the examples + +### Instructions + +All examples can be run individually. For example: + +``` +./gradlew run --args="us-east-1" +``` + +### Hello {Service} + +This example shows you how to get started using {AWS Service}. + +``` +./gradlew run --args="us-east-1" +``` + +### Get started with {Service} resources + +This interactive scenario runs at a command prompt and shows you how to use {AWS Service} to do the following: + +1. Create a resource +2. Use the resource +3. Clean up resources + +``` +./gradlew run --args="us-east-1" +``` + +## Run the tests + +Unit tests in this module use JUnit 5 and MockK. To run all of the tests, +run the following in your [GitHub root]/kotlin/services/{service} folder. + +``` +./gradlew test +``` + +## Additional resources + +- [{AWS Service} User Guide](https://docs.aws.amazon.com/{service}/latest/ug/) +- [{AWS Service} API Reference](https://docs.aws.amazon.com/{service}/latest/APIReference/) +- [AWS SDK for Kotlin ({AWS Service})](https://sdk.amazonaws.com/kotlin/api/latest/{service}/index.html) +``` + +## Documentation Dependencies + +### Required Files for README Generation +- ✅ **Metadata file**: `.doc_gen/metadata/{service}_metadata.yaml` +- ✅ **Code files**: All referenced Kotlin files must exist +- ✅ **Snippet tags**: All snippet tags in metadata must exist in code +- ✅ **Build file**: `build.gradle.kts` with dependencies + +### Metadata Integration +The writeme tool uses metadata to: +- Generate example lists and descriptions +- Create links to specific code sections +- Include proper service information +- Format documentation consistently + +## Troubleshooting README Generation + +### Common Issues +- **Missing metadata**: Ensure metadata file exists and is valid +- **Broken snippet tags**: Verify all snippet tags exist in code +- **File not found**: Check all file paths in metadata +- **Invalid YAML**: Validate metadata YAML syntax + +### Error Resolution +```bash +# Check for metadata errors +python -m writeme --languages Kotlin:1 --services {service} --verbose + +# Validate specific metadata file +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Check for missing snippet tags +grep -r "snippet-start" kotlin/services/{service}/ +``` + +## README Maintenance + +### When to Regenerate README +- ✅ **After adding new examples** +- ✅ **After updating metadata** +- ✅ **After changing code structure** +- ✅ **Before committing changes** +- ✅ **During regular maintenance** + +### README Quality Checklist +- ✅ **All examples listed** and properly linked +- ✅ **Prerequisites accurate** and complete +- ✅ **Installation instructions** work correctly +- ✅ **Usage examples** are clear and correct +- ✅ **Links functional** and point to right locations +- ✅ **Formatting consistent** with other services + +## Kotlin-Specific README Elements + +### Gradle Commands +README includes proper Gradle commands for: +- **Compilation**: `./gradlew build` +- **Execution**: `./gradlew run --args="..."` +- **Testing**: `./gradlew test` + +### Prerequisites +Kotlin-specific prerequisites: +- Kotlin 1.9 or later +- Gradle 8.0 or later +- AWS credentials configured + +### Code Links +Links point to specific Kotlin files: +- Actions: `src/main/kotlin/com/kotlin/{service}/{Service}Actions.kt` +- Scenarios: `src/main/kotlin/com/kotlin/{service}/{Service}Basics.kt` +- Hello: `src/main/kotlin/com/kotlin/{service}/Hello{Service}.kt` + +### Coroutines Information +Include information about coroutines usage: +```markdown +## Coroutines + +This project uses Kotlin coroutines for asynchronous operations. All AWS SDK calls are suspend functions that should be called from within a coroutine scope. + +```kotlin +suspend fun main() { + // Your async code here +} +``` +``` + +## Integration with CI/CD + +### Automated README Validation +```bash +# In CI/CD pipeline, validate README is up-to-date +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Kotlin:1 --services {service} --check + +# Exit with error if README needs updates +if git diff --exit-code kotlin/services/{service}/README.md; then + echo "README is up-to-date" +else + echo "README needs to be regenerated" + exit 1 +fi +``` + +### Build Integration +Ensure README generation is part of the build process: + +```kotlin +// In build.gradle.kts +tasks.register("generateReadme") { + group = "documentation" + description = "Generate README using writeme tool" + + workingDir = file("../../.tools/readmes") + commandLine = listOf( + "python", "-m", "writeme", + "--languages", "Kotlin:1", + "--services", "{service}" + ) +} + +tasks.named("build") { + dependsOn("generateReadme") +} +``` + +## Kotlin-Specific Documentation Features + +### Suspend Function Documentation +Document suspend functions properly: +```markdown +### Async Operations + +All AWS operations in this example are implemented as suspend functions: + +```kotlin +suspend fun createResource(client: {Service}Client): String { + // Implementation +} +``` + +Make sure to call these functions from within a coroutine scope. +``` + +### Extension Function Documentation +Document extension functions when used: +```markdown +### Extension Functions + +This example includes extension functions for common operations: + +```kotlin +fun List.filterActive(): List { + return filter { it.status == ResourceStatus.Active } +} +``` +``` + +### Null Safety Documentation +Highlight Kotlin's null safety features: +```markdown +### Null Safety + +This example leverages Kotlin's null safety features: + +```kotlin +val resource: Resource? = getResource(id) +resource?.let { + println("Resource found: ${it.name}") +} +``` +``` + +This ensures documentation stays synchronized with code changes and maintains consistency across all Kotlin examples while highlighting Kotlin-specific features and patterns. \ No newline at end of file diff --git a/steering_docs/kotlin-tech/tests.md b/steering_docs/kotlin-tech/tests.md new file mode 100644 index 00000000000..758e920d1af --- /dev/null +++ b/steering_docs/kotlin-tech/tests.md @@ -0,0 +1,532 @@ +# Kotlin Test Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Kotlin-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Kotlin-premium-KB", "Kotlin implementation patterns testing") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate comprehensive test suites including unit tests, integration tests, and scenario tests using JUnit 5 and MockK for AWS SDK for Kotlin. + +## Requirements +- **JUnit 5**: Use JUnit Jupiter for all tests +- **MockK**: Mock AWS SDK clients for unit tests +- **Coroutines Testing**: Use kotlinx-coroutines-test for suspend function testing +- **Complete Data**: Use complete AWS data structures in tests +- **Test Tags**: Use JUnit tags for test categorization +- **Error Coverage**: Test all error conditions from specification + +## File Structure +``` +kotlin/services/{service}/src/test/kotlin/ +├── {Service}ActionsTest.kt # Unit tests for actions +├── {Service}IntegrationTest.kt # Integration tests +└── {Service}ScenarioTest.kt # Scenario tests +``` + +## Gradle Test Configuration + +### Dependencies in build.gradle.kts +```kotlin +plugins { + kotlin("jvm") version "1.9.10" + application +} + +dependencies { + // AWS SDK + implementation("aws.sdk.kotlin:{service}:1.0.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") + + // Test Dependencies + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.10.0") + testImplementation("io.mockk:mockk:1.13.8") + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") +} + +tasks.test { + useJUnitPlatform() + exclude("**/*IntegrationTest*") +} + +tasks.register("integrationTest") { + useJUnitPlatform() + include("**/*IntegrationTest*") + group = "verification" + description = "Runs integration tests" +} +``` + +## Unit Test Pattern +```kotlin +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.kotlin.{service} + +import aws.sdk.kotlin.services.{service}.{Service}Client +import aws.sdk.kotlin.services.{service}.model.* +import aws.smithy.kotlin.runtime.ServiceException +import io.mockk.* +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Tag +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertNotNull + +@Tag("unit") +class {Service}ActionsTest { + + private lateinit var mockClient: {Service}Client + private lateinit var {service}Actions: {Service}Actions + + @BeforeEach + fun setUp() { + mockClient = mockk() + {service}Actions = {Service}Actions() + } + + @Test + fun `test {actionName} success`() = runTest { + // Arrange + val testParam = "test-value" + val expectedResponse = {ActionName}Response { + {responseField} = "response-value" + } + + coEvery { mockClient.{actionName}(any<{ActionName}Request>()) } returns expectedResponse + + // Act + val result = {service}Actions.{actionName}(mockClient, testParam) + + // Assert + assertNotNull(result) + assertEquals("response-value", result.{responseField}) + + coVerify { mockClient.{actionName}(any<{ActionName}Request>()) } + } + + @ParameterizedTest + @ValueSource(strings = ["BadRequestException", "InternalServerErrorException", "ResourceNotFoundException"]) + fun `test {actionName} service exception`(errorCode: String) = runTest { + // Arrange + val testParam = "test-value" + val serviceException = {Service}Exception.builder { + message = "Test error message" + }.build() + + coEvery { mockClient.{actionName}(any<{ActionName}Request>()) } throws serviceException + + // Act & Assert + assertFailsWith<{Service}Exception> { + {service}Actions.{actionName}(mockClient, testParam) + } + + coVerify { mockClient.{actionName}(any<{ActionName}Request>()) } + } + + @Test + fun `test {actionName} general exception`() = runTest { + // Arrange + val testParam = "test-value" + val exception = RuntimeException("General error") + + coEvery { mockClient.{actionName}(any<{ActionName}Request>()) } throws exception + + // Act & Assert + assertFailsWith { + {service}Actions.{actionName}(mockClient, testParam) + } + + coVerify { mockClient.{actionName}(any<{ActionName}Request>()) } + } + + @Test + fun `test list{Resources} with pagination`() = runTest { + // Arrange + val page1Response = List{Resources}Response { + {resources} = listOf( + {Resource} { + {resourceId} = "resource-1" + {resourceName} = "test-resource-1" + }, + {Resource} { + {resourceId} = "resource-2" + {resourceName} = "test-resource-2" + } + ) + nextToken = "token-1" + } + + val page2Response = List{Resources}Response { + {resources} = listOf( + {Resource} { + {resourceId} = "resource-3" + {resourceName} = "test-resource-3" + } + ) + nextToken = null + } + + coEvery { mockClient.list{Resources}(match { it.nextToken == null }) } returns page1Response + coEvery { mockClient.list{Resources}(match { it.nextToken == "token-1" }) } returns page2Response + + // Act + val result = {service}Actions.list{Resources}(mockClient) + + // Assert + assertEquals(3, result.size) + assertEquals("resource-1", result[0].{resourceId}) + assertEquals("resource-2", result[1].{resourceId}) + assertEquals("resource-3", result[2].{resourceId}) + + coVerify(exactly = 2) { mockClient.list{Resources}(any()) } + } +} +``` + +## Complete AWS Data Structures + +### CRITICAL: Use Complete AWS Response Data +```kotlin +// ❌ WRONG - Minimal data that fails validation +val resources = listOf( + {Resource} { + {resourceId} = "resource-1" + } +) + +// ✅ CORRECT - Complete AWS data structure +val resources = listOf( + {Resource} { + {resourceId} = "resource-1" + {resourceName} = "test-resource" + {resourceArn} = "arn:aws:service:region:account:resource/resource-1" + {resourceStatus} = {ResourceStatus}.Active + {createdAt} = aws.smithy.kotlin.runtime.time.Instant.now() + {updatedAt} = aws.smithy.kotlin.runtime.time.Instant.now() + {tags} = mapOf("Environment" to "Test") + } +) +``` + +## Integration Test Pattern +```kotlin +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.kotlin.{service} + +import aws.sdk.kotlin.services.{service}.{Service}Client +import aws.sdk.kotlin.services.{service}.model.* +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.AfterAll +import kotlin.test.assertNotNull +import kotlin.test.assertTrue +import kotlin.test.assertEquals + +@Tag("integration") +class {Service}IntegrationTest { + + companion object { + private lateinit var {service}Client: {Service}Client + private lateinit var {service}Actions: {Service}Actions + private var testResourceId: String? = null + + @BeforeAll + @JvmStatic + fun setUp() { + {service}Client = {Service}Client { + region = "us-east-1" + } + {service}Actions = {Service}Actions() + } + + @AfterAll + @JvmStatic + fun tearDown() = runTest { + // Clean up test resources + testResourceId?.let { resourceId -> + try { + {service}Actions.deleteResource({service}Client, resourceId) + } catch (e: Exception) { + // Ignore cleanup errors + } + } + {service}Client.close() + } + } + + @Test + fun `test resource lifecycle`() = runTest { + try { + // Create resource + testResourceId = {service}Actions.createResource({service}Client, "test-resource") + assertNotNull(testResourceId) + + // Get resource + val resource = {service}Actions.getResource({service}Client, testResourceId!!) + assertNotNull(resource) + assertEquals(testResourceId, resource.{resourceId}) + + // List resources (should include our test resource) + val resources = {service}Actions.listResources({service}Client) + assertTrue(resources.any { it.{resourceId} == testResourceId }) + + } catch (e: Exception) { + throw AssertionError("Integration test failed: ${e.message}", e) + } + } + + @Test + fun `test service connectivity`() = runTest { + // Test basic service connectivity + val resources = {service}Actions.listResources({service}Client) + assertNotNull(resources) + } +} +``` + +## Scenario Test Pattern +```kotlin +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.kotlin.{service} + +import aws.sdk.kotlin.services.{service}.{Service}Client +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Tag +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.AfterEach +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.PrintStream +import kotlin.test.assertTrue + +@Tag("integration") +class {Service}ScenarioTest { + + private lateinit var {service}Client: {Service}Client + private lateinit var outputStream: ByteArrayOutputStream + private lateinit var originalOut: PrintStream + + @BeforeEach + fun setUp() { + {service}Client = {Service}Client { + region = "us-east-1" + } + + // Capture System.out for testing + outputStream = ByteArrayOutputStream() + originalOut = System.out + System.setOut(PrintStream(outputStream)) + } + + @AfterEach + fun tearDown() = runTest { + System.setOut(originalOut) + {service}Client.close() + } + + @Test + fun `test scenario with mocked input`() = runTest { + // Mock user inputs for automated testing + val simulatedInput = "n\nn\ny\n" // No existing resource, no details, yes cleanup + System.setIn(ByteArrayInputStream(simulatedInput.toByteArray())) + + // Run scenario + try { + // Assuming main function exists in {Service}Basics or similar + main(arrayOf("us-east-1")) + } catch (e: Exception) { + throw AssertionError("Scenario test failed: ${e.message}", e) + } + + // Verify output contains expected messages + val output = outputStream.toString() + assertTrue(output.contains("Welcome to the {AWS Service} basics scenario!")) + assertTrue(output.contains("Setting up {AWS Service}")) + } + + @Test + fun `test scenario with existing resources`() = runTest { + // Create a test resource first + var testResourceId: String? = null + try { + val actions = {Service}Actions() + testResourceId = actions.createResource({service}Client, "test-resource") + + // Mock user inputs to use existing resource + val simulatedInput = "y\nn\ny\n" // Yes existing, no details, yes cleanup + System.setIn(ByteArrayInputStream(simulatedInput.toByteArray())) + + // Run scenario + main(arrayOf("us-east-1")) + + val output = outputStream.toString() + assertTrue(output.contains("Found")) + assertTrue(output.contains("existing resource")) + + } finally { + // Clean up test resource + testResourceId?.let { resourceId -> + try { + {Service}Actions().deleteResource({service}Client, resourceId) + } catch (e: Exception) { + // Ignore cleanup errors + } + } + } + } +} +``` + +## Test Execution Commands + +### Unit Tests Only +```bash +cd kotlin/services/{service} +./gradlew test --exclude-task integrationTest +``` + +### Integration Tests Only +```bash +cd kotlin/services/{service} +./gradlew integrationTest +``` + +### All Tests +```bash +cd kotlin/services/{service} +./gradlew test integrationTest +``` + +### Specific Test Class +```bash +./gradlew test --tests "{Service}ActionsTest" +``` + +## Coroutines Testing + +### Using runTest +```kotlin +@Test +fun `test suspend function`() = runTest { + // Test suspend functions here + val result = suspendingFunction() + assertNotNull(result) +} +``` + +### Testing Coroutine Scope +```kotlin +@Test +fun `test with custom scope`() = runTest { + val testScope = TestScope() + + testScope.launch { + // Test coroutine operations + } + + testScope.advanceUntilIdle() +} +``` + +## Test Requirements Checklist +- ✅ **JUnit 5 annotations** (@Test, @BeforeEach, @AfterEach) +- ✅ **MockK for unit tests** (mockk(), coEvery, coVerify) +- ✅ **Coroutines testing** (runTest, TestScope) +- ✅ **Complete AWS data structures** in all tests +- ✅ **Proper test tags** (@Tag("integration")) +- ✅ **Error condition coverage** per specification +- ✅ **Integration test cleanup** (try/finally blocks) +- ✅ **Region specification** ("us-east-1") +- ✅ **Resource lifecycle testing** (create, read, delete) +- ✅ **Parameterized tests** for multiple error conditions + +## Test Categories + +### Unit Tests +- ✅ **Mock AWS clients** using MockK +- ✅ **Test individual suspend functions** in isolation +- ✅ **Cover success and error cases** +- ✅ **Fast execution** (no real AWS calls) + +### Integration Tests +- ✅ **Use real AWS clients** and services +- ✅ **Test complete workflows** end-to-end +- ✅ **Require AWS credentials** and permissions +- ✅ **Include cleanup logic** to avoid resource leaks + +### Scenario Tests +- ✅ **Test complete scenarios** with mocked user input +- ✅ **Verify console output** and user interactions +- ✅ **Test multiple user paths** (existing resources, new resources) +- ✅ **Integration test category** (requires real AWS) + +## Common Test Failures to Avoid +- ❌ Using incomplete AWS data structures in mocks +- ❌ Missing test tags for integration tests +- ❌ Not handling cleanup in integration tests +- ❌ Forgetting to set AWS region in test clients +- ❌ Not testing all error conditions from specification +- ❌ Not mocking user inputs in scenario tests +- ❌ Missing Gradle test configuration +- ❌ Not using runTest for suspend function tests +- ❌ Incorrect MockK usage (coEvery vs every) + +## Kotlin-Specific Testing Features + +### Suspend Function Testing +```kotlin +@Test +fun `test suspend function`() = runTest { + val result = suspendFunction() + assertNotNull(result) +} +``` + +### Coroutine Exception Testing +```kotlin +@Test +fun `test coroutine exception`() = runTest { + assertFailsWith { + suspendFunctionThatThrows() + } +} +``` + +### Extension Function Testing +```kotlin +@Test +fun `test extension function`() { + val resources = listOf(/* test data */) + val filtered = resources.filterActive() + assertEquals(expectedCount, filtered.size) +} +``` \ No newline at end of file diff --git a/steering_docs/python-tech-original.md b/steering_docs/python-tech-original.md new file mode 100644 index 00000000000..5b378e4791c --- /dev/null +++ b/steering_docs/python-tech-original.md @@ -0,0 +1,561 @@ +# Python Technology Stack & Build System + +## 🚨 READ THIS FIRST - MANDATORY WORKFLOW 🚨 + +**BEFORE CREATING ANY PYTHON CODE FOR AWS SERVICES:** + +1. **FIRST**: Run knowledge base consultation (ListKnowledgeBases + QueryKnowledgeBases) +2. **SECOND**: Create service stubber in `python/test_tools/{service}_stubber.py` +3. **THIRD**: Add stubber to `python/test_tools/stubber_factory.py` +4. **FOURTH**: Create conftest.py with ScenarioData class +5. **FIFTH**: Create implementation files with complete AWS data structures +6. **SIXTH**: Run ALL mandatory commands (pytest, black, pylint, writeme) + +**❌ SKIPPING ANY STEP = REJECTED CODE** +**❌ WRONG ORDER = REJECTED CODE** +**❌ INCOMPLETE DATA STRUCTURES = REJECTED CODE** + +## Python 3.6+ Development Environment + +### Build Tools & Dependencies +- **Package Manager**: pip +- **Virtual Environment**: venv +- **Testing Framework**: pytest +- **Code Formatting**: black +- **Linting**: pylint, flake8 +- **Type Checking**: mypy (where applicable) + +### Common Build Commands + +```bash +# Environment Setup +python -m venv .venv +source .venv/bin/activate # Linux/macOS +.venv\Scripts\activate # Windows + +# Dependencies +pip install -r requirements.txt + +# Testing +python -m pytest -m "not integ" # Unit tests +python -m pytest -m "integ" # Integration tests + +# Code Quality +black . # Format code +pylint --rcfile=.github/linters/.python-lint . +``` + +## 🚨 CRITICAL: MANDATORY WORKFLOW BEFORE ANY CODE CREATION 🚨 + +### STEP-BY-STEP MANDATORY SEQUENCE (MUST BE FOLLOWED EXACTLY) + +**❌ COMMON MISTAKES THAT LEAD TO REJECTED CODE:** +- Creating any files before knowledge base consultation +- Creating conftest.py before service stubber +- Skipping ScenarioData class for complex services +- Using incomplete AWS data structures in tests +- Not running proper pytest markers +- Skipping code formatting and linting + +**✅ CORRECT MANDATORY SEQUENCE:** + +**STEP 1: KNOWLEDGE BASE CONSULTATION (REQUIRED FIRST)** +```bash +# MUST be done before creating ANY files +ListKnowledgeBases() +QueryKnowledgeBases("coding-standards-KB", "Python-code-example-standards") +QueryKnowledgeBases("Python-premium-KB", "Python implementation patterns") +``` + +**STEP 2: CREATE SERVICE STUBBER (REQUIRED BEFORE CONFTEST)** +```bash +# Check if python/test_tools/{service}_stubber.py exists +# If missing, create it following existing patterns +# Add to python/test_tools/stubber_factory.py +``` + +**STEP 3: CREATE CONFTEST.PY WITH SCENARIODATA** +```bash +# Create python/example_code/{service}/test/conftest.py +# MUST include ScenarioData class for complex services +# Import from test_tools.fixtures.common import * +``` + +**STEP 4: CREATE IMPLEMENTATION FILES** +```bash +# Create wrapper, hello, scenario files +# Use complete AWS data structures (not minimal ones) +``` + +**STEP 5: MANDATORY TESTING AND QUALITY** +```bash +# MUST run these exact commands: +python -m pytest -m "not integ" # Unit tests +python -m pytest -m "integ" # Integration tests +black . # Format code +pylint --rcfile=.github/linters/.python-lint . +python -m writeme --languages Python:3 --services {service} +``` + +### Python-Specific Pattern Requirements + +#### File Naming Conventions +- Use snake_case for all Python files +- Service prefix pattern: `{service}_action.py` (e.g., `s3_list_buckets.py`) +- Scenario files: `{service}_basics.py` or `{service}_scenario.py` +- Test files: `test_{service}_action.py` + +#### Hello Scenario Structure +- **File naming**: `{service}_hello.py` or hello function in main module +- **Function naming**: `hello_{service}()` or `main()` +- **Documentation**: Include docstrings explaining the hello example purpose + +#### Scenario Pattern Structure +**MANDATORY for all scenario files:** + +```python +# scenario_{service}_basics.py structure +import logging +import os +import sys +from typing import Optional + +import boto3 +from botocore.exceptions import ClientError + +from {service}_wrapper import {Service}Wrapper + +# Add relative path to include demo_tools +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "../..")) +from demo_tools import question as q + +logger = logging.getLogger(__name__) + +class {Service}Scenario: + """Runs an interactive scenario that shows how to use {AWS Service}.""" + + def __init__(self, {service}_wrapper: {Service}Wrapper): + """ + :param {service}_wrapper: An instance of the {Service}Wrapper class. + """ + self.{service}_wrapper = {service}_wrapper + + def run_scenario(self): + """Runs the {AWS Service} basics scenario.""" + print("-" * 88) + print("Welcome to the {AWS Service} basics scenario!") + print("-" * 88) + + try: + self._setup_phase() + self._demonstration_phase() + self._examination_phase() + except Exception as e: + logger.error(f"Scenario failed: {e}") + finally: + self._cleanup_phase() + + def _setup_phase(self): + """Setup phase implementation.""" + pass + + def _demonstration_phase(self): + """Demonstration phase implementation.""" + pass + + def _examination_phase(self): + """Examination phase implementation.""" + pass + + def _cleanup_phase(self): + """Cleanup phase implementation.""" + pass + +def main(): + """Runs the {AWS Service} basics scenario.""" + logging.basicConfig(level=logging.WARNING, format="%(levelname)s: %(message)s") + + try: + {service}_wrapper = {Service}Wrapper.from_client() + scenario = {Service}Scenario({service}_wrapper) + scenario.run_scenario() + except Exception as e: + logger.error(f"Failed to run scenario: {e}") + +if __name__ == "__main__": + main() +``` + +**Scenario Requirements:** +- ✅ **ALWAYS** include descriptive comment block at top explaining scenario steps +- ✅ **ALWAYS** use demo_tools for user interaction +- ✅ **ALWAYS** implement proper cleanup in finally block +- ✅ **ALWAYS** break scenario into logical phases +- ✅ **ALWAYS** include comprehensive error handling + +#### Code Structure Standards +- **Imports**: Follow PEP 8 import ordering (standard library, third-party, local) +- **Functions**: Use descriptive names with snake_case +- **Classes**: Use PascalCase for class names +- **Constants**: Use UPPER_CASE for constants +- **Type Hints**: Include type annotations where beneficial + +#### Wrapper Class Pattern +**MANDATORY for all services:** + +```python +# {service}_wrapper.py structure +import logging +import boto3 +from botocore.exceptions import ClientError +from typing import Dict, List, Optional, Any + +logger = logging.getLogger(__name__) + +class {Service}Wrapper: + """Encapsulates {AWS Service} functionality.""" + + def __init__(self, {service}_client: boto3.client): + """ + :param {service}_client: A Boto3 {AWS Service} client. + """ + self.{service}_client = {service}_client + + @classmethod + def from_client(cls): + {service}_client = boto3.client("{service}") + return cls({service}_client) + + # Individual action methods with proper error handling + def action_method(self, param: str) -> Dict[str, Any]: + """ + Action description. + + :param param: Parameter description. + :return: Response description. + """ + try: + response = self.{service}_client.action_name(Parameter=param) + logger.info(f"Action completed successfully") + return response + except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "SpecificError": + logger.error("Specific error handling") + else: + logger.error(f"Error in action: {e}") + raise +``` + +**Wrapper Class Requirements:** +- ✅ **ALWAYS** include proper logging +- ✅ **ALWAYS** provide `from_client()` class method +- ✅ **ALWAYS** handle service-specific errors +- ✅ **ALWAYS** include comprehensive docstrings +- ✅ **ALWAYS** use type hints for parameters and returns + +#### Testing Convention and Structure + +**🚨 MANDATORY Testing Infrastructure Setup (EXACT ORDER REQUIRED):** + +**❌ CRITICAL ERROR: Creating conftest.py before service stubber will cause failures** + +**✅ CORRECT ORDER:** + +1. **FIRST: Create Service Stubber (MANDATORY BEFORE CONFTEST):** + - **CRITICAL**: Check if `python/test_tools/{service}_stubber.py` exists + - **CRITICAL**: If missing, create it FIRST following existing patterns (e.g., `controltower_stubber.py`) + - **CRITICAL**: Inherit from `ExampleStubber` and implement ALL service-specific stub methods + - **CRITICAL**: Add to `python/test_tools/stubber_factory.py` import and factory function + - **CRITICAL**: Each stub method MUST handle both stubbing and AWS passthrough modes + +2. **SECOND: Create Service conftest.py (ONLY AFTER STUBBER EXISTS):** + - **CRITICAL**: Create `python/example_code/{service}/test/conftest.py` + - **CRITICAL**: Import common fixtures: `from test_tools.fixtures.common import *` + - **CRITICAL**: Add path configuration: `sys.path.append("../..")` + - **CRITICAL**: For complex services, MUST create ScenarioData class (not optional) + - **CRITICAL**: Use complete AWS data structures in tests (not minimal ones) + +3. **Test File Structure:** + - **Unit Tests**: `test_{service}_wrapper.py` - Test wrapper class methods with mocked responses + - **Integration Tests**: `test_{service}_integration.py` - Test against real AWS services (marked with `@pytest.mark.integ`) + - **Scenario Tests**: `test_{service}_scenario.py` - Test complete scenarios end-to-end + +**Testing Pattern Examples:** + +```python +# Simple conftest.py pattern +import sys +sys.path.append("../..") +from test_tools.fixtures.common import * + +# Complex conftest.py with ScenarioData class +class ScenarioData: + def __init__(self, service_client, service_stubber): + self.service_client = service_client + self.service_stubber = service_stubber + self.wrapper = ServiceWrapper(service_client) + +@pytest.fixture +def scenario_data(make_stubber): + client = boto3.client("service") + stubber = make_stubber(client) + return ScenarioData(client, stubber) +``` + +**🚨 CRITICAL Testing Requirements:** +- ✅ **ALWAYS** use the centralized `test_tools` infrastructure +- ✅ **ALWAYS** support both stubbed and real AWS testing modes +- ✅ **ALWAYS** mark integration tests with `@pytest.mark.integ` +- ✅ **ALWAYS** ensure proper cleanup in integration tests +- ✅ **ALWAYS** use the `make_stubber` fixture for consistent stubbing +- ✅ **CRITICAL**: Use COMPLETE AWS data structures in tests (see below) + +**🚨 CRITICAL: Complete AWS Data Structures Required** + +**❌ COMMON MISTAKE: Using minimal test data that fails validation** +```python +# WRONG - Missing required AWS fields +findings = [{"Id": "finding-1", "Type": "SomeType", "Severity": 8.0}] +``` + +**✅ CORRECT: Complete AWS data structures** +```python +# RIGHT - All required AWS fields included +findings = [{ + "Id": "finding-1", + "AccountId": "123456789012", + "Arn": "arn:aws:service:region:account:resource/id", + "Type": "SomeType", + "Severity": 8.0, + "CreatedAt": "2023-01-01T00:00:00.000Z", + "UpdatedAt": "2023-01-01T00:00:00.000Z", + "Region": "us-east-1", + "SchemaVersion": "2.0", + "Resource": {"ResourceType": "Instance"} +}] +``` + +**CRITICAL**: Always check AWS API documentation for required fields before creating test data. + +#### Error Handling Patterns +```python +import boto3 +from botocore.exceptions import ClientError, NoCredentialsError + +def example_function(): + try: + # AWS service call + response = client.operation() + return response + except ClientError as e: + error_code = e.response['Error']['Code'] + if error_code == 'SpecificError': + # Handle specific error + pass + else: + # Handle general client errors + raise + except NoCredentialsError: + # Handle credential issues + raise +``` + +#### Testing Standards +- **Test markers**: Use `@pytest.mark.integ` for integration tests +- **Fixtures**: Create reusable fixtures for AWS resources +- **Cleanup**: Ensure proper resource cleanup in tests +- **Mocking**: Use `boto3` stubber for unit tests when appropriate + +#### Requirements File Pattern +**MANDATORY for every service directory:** + +```txt +# requirements.txt - minimum versions +boto3>=1.26.137 +botocore>=1.29.137 +``` + +**Requirements Guidelines:** +- ✅ **ALWAYS** specify minimum compatible versions +- ✅ **ALWAYS** include both boto3 and botocore +- ✅ **ALWAYS** test with specified minimum versions +- ✅ **NEVER** pin to exact versions unless absolutely necessary + +#### Documentation Requirements +- **Module docstrings**: Include purpose and usage examples +- **Function docstrings**: Follow Google or NumPy docstring format +- **Inline comments**: Explain complex AWS service interactions +- **README sections**: Include setup instructions and prerequisites +- **Snippet tags**: Include proper snippet tags for documentation generation + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER create scenarios without checking existing patterns** +- ❌ **NEVER use camelCase for Python variables or functions** +- ❌ **NEVER ignore proper exception handling for AWS operations** +- ❌ **NEVER skip virtual environment setup** + +### 🚨 MANDATORY COMPLETION CHECKLIST + +**❌ WORK IS NOT COMPLETE UNTIL ALL THESE COMMANDS PASS:** + +```bash +# 1. MANDATORY: Unit tests must pass +python -m pytest -m "not integ" -v + +# 2. MANDATORY: Integration tests must pass +python -m pytest -m "integ" -v + +# 3. MANDATORY: Code formatting must be applied +black . + +# 4. MANDATORY: Linting must pass +pylint --rcfile=.github/linters/.python-lint python/example_code/{service}/ + +# 5. MANDATORY: Documentation must be updated +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Python:3 --services {service} + +# 6. MANDATORY: ALL EXAMPLE FILES MUST BE EXECUTED TO VALIDATE CREATION +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/{service}_hello.py +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/scenario_{service}_basics.py +# Test wrapper functions directly +PYTHONPATH=python:python/example_code/{service} python -c "from {service}_wrapper import {Service}Wrapper; wrapper = {Service}Wrapper.from_client(); print('✅ Wrapper functions working')" +``` + +**🚨 CRITICAL**: If ANY of these commands fail, the work is INCOMPLETE and must be fixed. + +**🚨 MANDATORY VALIDATION REQUIREMENT**: +- **ALL generated example files MUST be executed successfully to validate their creation** +- **Hello examples MUST run without errors and display expected output** +- **Scenario examples MUST run interactively and complete all phases** +- **Wrapper classes MUST be importable and instantiable** +- **Any runtime errors or import failures indicate incomplete implementation** + +### Best Practices +- ✅ **ALWAYS follow the established `{service}_basics.py` or scenario patterns** +- ✅ **ALWAYS use snake_case naming conventions** +- ✅ **ALWAYS include proper error handling for AWS service calls** +- ✅ **ALWAYS use virtual environments for dependency management** +- ✅ **ALWAYS include type hints where they improve code clarity** +- ✅ **CRITICAL**: Follow the mandatory workflow sequence exactly +- ✅ **CRITICAL**: Use complete AWS data structures in all tests +- ✅ **CRITICAL**: Create service stubber before conftest.py +- ✅ **CRITICAL**: Include ScenarioData class for complex services + +#### Metadata File Pattern +**MANDATORY for documentation generation:** + +**CRITICAL**: Always check the specification file first for metadata requirements: +- **Specification Location**: `scenarios/basics/{service}/SPECIFICATION.md` +- **Metadata Section**: Contains exact metadata keys and structure to use +- **Use Spec Metadata As-Is**: Copy the metadata table from the specification exactly + +**Specification Metadata Table Format:** +``` +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`ActionName` |{service}_metadata.yaml |{service}_ActionName | +|`Service Basics Scenario` |{service}_metadata.yaml |{service}_Scenario | +``` + +**Implementation Steps:** +1. **Read Specification**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first +2. **Extract Metadata Table**: Use the exact metadata keys from the specification +3. **Create Metadata File**: Create `.doc_gen/metadata/{service}_metadata.yaml` +4. **Follow Spec Structure**: Use the metadata keys exactly as specified in the table + +**Standard Metadata Structure (when no spec exists):** +```yaml +# .doc_gen/metadata/{service}_metadata.yaml +{service}_Hello: + title: Hello &{Service}; + title_abbrev: Hello &{Service}; + synopsis: get started using &{Service};. + category: Hello + languages: + Python: + versions: + - sdk_version: 3 + github: python/example_code/{service} + excerpts: + - description: + snippet_tags: + - python.example_code.{service}.Hello + services: + {service}: {ListOperation} +``` + +**Metadata Requirements:** +- ✅ **ALWAYS** check specification file for metadata requirements FIRST +- ✅ **ALWAYS** use exact metadata keys from specification table +- ✅ **ALWAYS** include Hello scenario metadata +- ✅ **ALWAYS** include all action and scenario metadata as specified +- ✅ **ALWAYS** use proper snippet tags matching code +- ✅ **ALWAYS** validate metadata with writeme tool + +### Integration with Knowledge Base and Specifications + +**MANDATORY Pre-Implementation Workflow:** + +1. **Check Specification File FIRST:** + - **Location**: `scenarios/basics/{service}/SPECIFICATION.md` + - **Extract**: API actions, error handling requirements, metadata table + - **Use**: Exact metadata keys and structure from specification + +2. **Knowledge Base Consultation:** + - Query `coding-standards-KB` for "Python-code-example-standards" + - Query `Python-premium-KB` for "Python implementation patterns" + - Follow KB-documented patterns for file structure and naming + +3. **Implementation Priority:** + - **Specification requirements**: Use exact API actions and metadata from spec + - **KB patterns**: Follow established coding patterns and structure + - **Existing examples**: Validate against existing Python examples only after KB consultation + +**Critical Rule**: When specification exists, always use its metadata table exactly as provided. Never create custom metadata keys when specification defines them. +## 🚨 +COMMON FAILURE PATTERNS TO AVOID 🚨 + +### ❌ Pattern 1: Skipping Knowledge Base Consultation +**Mistake**: Starting to code immediately without KB research +**Result**: Wrong file structure, missing patterns, rejected code +**Fix**: ALWAYS do ListKnowledgeBases + QueryKnowledgeBases FIRST + +### ❌ Pattern 2: Wrong Testing Infrastructure Order +**Mistake**: Creating conftest.py before service stubber +**Result**: Import errors, test failures, broken infrastructure +**Fix**: Create stubber FIRST, then conftest.py + +### ❌ Pattern 3: Missing ScenarioData Class +**Mistake**: Using simple conftest.py for complex services +**Result**: Difficult test setup, inconsistent patterns +**Fix**: Always use ScenarioData class for services with scenarios + +### ❌ Pattern 4: Incomplete AWS Data Structures +**Mistake**: Using minimal test data missing required AWS fields +**Result**: Parameter validation errors, test failures +**Fix**: Use complete AWS data structures with all required fields + +### ❌ Pattern 5: Wrong Test Commands +**Mistake**: Using `pytest test/` instead of proper markers +**Result**: Not following established patterns, inconsistent testing +**Fix**: Use `python -m pytest -m "not integ"` and `python -m pytest -m "integ"` + +### ❌ Pattern 6: Skipping Code Quality +**Mistake**: Not running black, pylint, or writeme +**Result**: Inconsistent formatting, linting errors, outdated docs +**Fix**: ALWAYS run all mandatory commands before considering work complete + +### ✅ SUCCESS PATTERN: Follow the Exact Sequence +1. Knowledge base consultation +2. Service stubber creation +3. Stubber factory integration +4. Conftest.py with ScenarioData +5. Implementation with complete data structures +6. All mandatory commands execution + +**REMEMBER**: These patterns exist because they prevent the exact mistakes made in this session. Follow them exactly. \ No newline at end of file diff --git a/steering_docs/python-tech/basics.md b/steering_docs/python-tech/basics.md new file mode 100644 index 00000000000..2e59e9971d4 --- /dev/null +++ b/steering_docs/python-tech/basics.md @@ -0,0 +1,349 @@ +# Python Interactive Scenario Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Python-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Python-premium-KB", "Python implementation patterns structure") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate interactive scenarios that demonstrate complete workflows using multiple service operations in a guided, educational manner. Implementation must be based on the service SPECIFICATION.md file. + +## Requirements +- **Specification-Driven**: MUST read the `scenarios/basics/{service}/SPECIFICATION.md` +- **Interactive**: USE demo_tools for user input and guidance +- **Educational**: Break complex workflows into logical phases +- **Comprehensive**: Cover setup, demonstration, examination, and cleanup +- **Error Handling**: Graceful error handling with user-friendly messages +- **Wrapper Classes**: MUST use service wrapper classes for all operations + +## File Structure +``` +python/example_code/{service}/ +├── scenario_{service}_basics.py # Main scenario file +``` + +## MANDATORY Pre-Implementation Steps + +### Step 1: Read Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first to understand: +- **API Actions Used**: Exact operations to implement +- **Proposed Example Structure**: Setup, demonstration, examination, cleanup phases +- **Error Handling**: Specific error codes and handling requirements +- **Scenario Flow**: Step-by-step workflow description + +### Step 2: Extract Implementation Requirements +From the specification, identify: +- **Setup Phase**: What resources need to be created/configured +- **Demonstration Phase**: What operations to demonstrate +- **Examination Phase**: What data to display and how to filter/analyze +- **Cleanup Phase**: What resources to clean up and user options + +## Scenario Class Pattern +### Implementation Pattern Based on SPECIFICATION.md +```python +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Purpose + +Shows how to use {AWS Service} to {scenario description}. This scenario demonstrates: + +1. {Phase 1 description} +2. {Phase 2 description} +3. {Phase 3 description} +4. {Phase 4 description} + +This example uses the AWS SDK for Python (Boto3) to interact with {AWS Service}. +""" + +import logging +import sys +import time +from typing import List, Dict, Any + +import boto3 +from botocore.exceptions import ClientError + +from {service}_wrapper import {Service}Wrapper + +# Add relative path to include demo_tools +sys.path.insert(0, "../..") +from demo_tools import question as q + +logger = logging.getLogger(__name__) + + +# snippet-start:[python.example_code.{service}.{Service}Scenario] +class {Service}Scenario: + """Runs an interactive scenario that shows how to use {AWS Service}.""" + + def __init__(self, {service}_wrapper: {Service}Wrapper): + """ + :param {service}_wrapper: An instance of the {Service}Wrapper class. + """ + self.{service}_wrapper = {service}_wrapper + self.{resource_id} = None + + def run_scenario(self): + """Runs the {AWS Service} basics scenario.""" + print("-" * 88) + print("Welcome to the {AWS Service} basics scenario!") + print("-" * 88) + print( + "{Service description and what users will learn}" + ) + print() + + try: + self._setup_phase() + self._demonstration_phase() + self._examination_phase() + except Exception as e: + logger.error(f"Scenario failed: {e}") + print(f"The scenario encountered an error: {e}") + finally: + self._cleanup_phase() + + def _setup_phase(self): + """Setup phase: Implement based on specification's Setup section.""" + print("Setting up {AWS Service}...") + print() + + # Example: Check for existing resources (from specification) + existing_resources = self.{service}_wrapper.list_resources() + if existing_resources: + print(f"Found {len(existing_resources)} existing resource(s):") + for resource in existing_resources: + print(f" - {resource}") + + use_existing = q.ask( + "Would you like to use an existing resource? (y/n): ", q.is_yesno + ) + if use_existing: + self.resource_id = existing_resources[0] + return + + def _demonstration_phase(self): + """Demonstration phase: Implement operations from specification.""" + print("Demonstrating {AWS Service} capabilities...") + print() + + # Implement specific operations from specification + # Example: Generate sample data if specified + self.{service}_wrapper.create_sample_data(self.resource_id) + print("✓ Sample data created successfully") + + # Wait if specified in the specification + print("Waiting for data to be processed...") + time.sleep(5) + + def _examination_phase(self): + """Examination phase: Implement data analysis from specification.""" + print("Examining {AWS Service} data...") + print() + + # List and examine data as specified + data_items = self.{service}_wrapper.list_data(self.resource_id) + if not data_items: + print("No data found. Data may take a few minutes to appear.") + return + + print(f"Found {len(data_items)} data item(s)") + + # Get detailed information as specified + detailed_data = self.{service}_wrapper.get_data_details(self.resource_id, data_items[:5]) + self._display_data_summary(detailed_data) + + # Show detailed view if specified + if detailed_data: + show_details = q.ask( + "Would you like to see detailed information? (y/n): ", q.is_yesno + ) + if show_details: + self._display_data_details(detailed_data[0]) + + # Filter data as specified + self._filter_data_by_criteria(data_items) + + def _cleanup_phase(self): + """Cleanup phase: Implement cleanup options from specification.""" + if not self.resource_id: + return + + print("Cleanup options:") + print("Note: Deleting the resource will stop all monitoring/processing.") + + delete_resource = q.ask( + "Would you like to delete the resource? (y/n): ", q.is_yesno + ) + + if delete_resource: + try: + self.{service}_wrapper.delete_resource(self.resource_id) + print(f"✓ Deleted resource: {self.resource_id}") + except Exception as e: + print(f"Error deleting resource: {e}") + else: + print(f"Resource {self.resource_id} will continue running.") + print("You can manage it through the AWS Console or delete it later.") +# snippet-end:[python.example_code.{service}.{Service}Scenario] + + +def main(): + """Runs the {AWS Service} basics scenario.""" + logging.basicConfig(level=logging.WARNING, format="%(levelname)s: %(message)s") + + try: + {service}_wrapper = {Service}Wrapper.from_client() + scenario = {Service}Scenario({service}_wrapper) + scenario.run_scenario() + except Exception as e: + logger.error(f"Failed to run scenario: {e}") + print(f"Failed to run the scenario: {e}") + + +if __name__ == "__main__": + main() +``` + +## Scenario Phase Structure (Based on Specification) + +### Setup Phase +- **Read specification Setup section** for exact requirements +- Check for existing resources as specified +- Create necessary resources using wrapper methods +- Configure service settings per specification +- Verify setup completion as described + +### Demonstration Phase +- **Follow specification Demonstration section** exactly +- Perform core service operations using wrapper methods +- Generate sample data if specified in the specification +- Show service capabilities as outlined +- Provide educational context from specification + +### Examination Phase +- **Implement specification Examination section** requirements +- List and examine results using wrapper methods +- Filter and analyze data as specified +- Display detailed information per specification format +- Allow user interaction as described in specification + +### Cleanup Phase +- **Follow specification Cleanup section** guidance +- Offer cleanup options with warnings from specification +- Handle cleanup errors gracefully using wrapper methods +- Provide alternative management options as specified +- Confirm completion per specification + +## User Interaction Patterns + +### Question Types +```python +# Yes/No questions +use_existing = q.ask("Use existing resource? (y/n): ", q.is_yesno) + +# Text input +resource_name = q.ask("Enter resource name: ") + +# Numeric input +count = q.ask("How many items? ", q.is_int) +``` + +### Information Display +```python +# Progress indicators +print("✓ Operation completed successfully") +print("⚠ Warning message") +print("✗ Error occurred") + +# Formatted output +print("-" * 60) +print(f"Found {len(items)} items:") +for item in items: + print(f" • {item['name']}") +``` + +## Specification-Based Error Handling + +### Error Handling from Specification +The specification includes an "Errors" section with specific error codes and handling: + +```python +# Example error handling based on specification +try: + response = self.{service}_wrapper.create_resource() + return response +except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "BadRequestException": + # Handle as specified: "Validate input parameters and notify user" + print("Invalid configuration. Please check your parameters.") + elif error_code == "InternalServerErrorException": + # Handle as specified: "Retry operation with exponential backoff" + print("Service temporarily unavailable. Retrying...") + # Implement retry logic + else: + print(f"Unexpected error: {e}") + raise +``` + +## Scenario Requirements +- ✅ **ALWAYS** read and implement based on `scenarios/basics/{service}/SPECIFICATION.md` +- ✅ **ALWAYS** include descriptive comment block at top explaining scenario steps from specification +- ✅ **ALWAYS** use demo_tools for user interaction +- ✅ **ALWAYS** use service wrapper classes for all AWS operations +- ✅ **ALWAYS** implement proper cleanup in finally block +- ✅ **ALWAYS** break scenario into logical phases per specification +- ✅ **ALWAYS** include error handling per specification's Errors section +- ✅ **ALWAYS** provide educational context and explanations from specification +- ✅ **ALWAYS** handle edge cases (no resources found, etc.) as specified + +## Implementation Workflow + +### Step-by-Step Implementation Process +1. **Read Specification**: Study `scenarios/basics/{service}/SPECIFICATION.md` thoroughly +2. **Extract API Actions**: Note all API actions listed in "API Actions Used" section +3. **Map to Wrapper Methods**: Ensure wrapper class has methods for all required actions +4. **Implement Phases**: Follow the "Proposed example structure" section exactly +5. **Add Error Handling**: Implement error handling per the "Errors" section +6. **Test Against Specification**: Verify implementation matches specification requirements + +### Specification Sections to Implement +- **API Actions Used**: All operations must be available in wrapper class +- **Proposed example structure**: Direct mapping to scenario phases +- **Setup**: Exact setup steps and resource creation +- **Demonstration**: Specific operations to demonstrate +- **Examination**: Data analysis and filtering requirements +- **Cleanup**: Resource cleanup options and user choices +- **Errors**: Specific error codes and handling strategies + +## Error Handling in Scenarios +- **Follow specification error table**: Implement exact error handling per specification +- Catch and display user-friendly error messages per specification guidance +- Continue scenario execution when possible as specified +- Provide guidance on resolving issues from specification +- Ensure cleanup runs even if errors occur + +## Educational Elements +- **Use specification descriptions**: Explain operations using specification language +- Show before/after states as outlined in specification +- Provide context about service capabilities from specification +- Include tips and best practices mentioned in specification +- Follow the educational flow described in specification structure \ No newline at end of file diff --git a/steering_docs/python-tech/hello.md b/steering_docs/python-tech/hello.md new file mode 100644 index 00000000000..8718ea02d3e --- /dev/null +++ b/steering_docs/python-tech/hello.md @@ -0,0 +1,120 @@ +# Python Hello Examples Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Python-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Python-premium-KB", "Python implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate simple "Hello" examples that demonstrate basic service connectivity and the most fundamental operation using direct boto3 client calls. + +## Requirements +- **MANDATORY**: Every AWS service MUST include a "Hello" scenario +- **Simplicity**: Should be the most basic, minimal example possible +- **Standalone**: Must work independently of other examples +- **Direct Client**: Use boto3 client directly, no wrapper classes needed + +## File Structure +``` +python/example_code/{service}/ +├── {service}_hello.py # Hello example file +``` + +## Hello Example Pattern +```python +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Purpose + +Shows how to get started with {AWS Service} by {basic operation description}. +""" + +import logging +import boto3 +from botocore.exceptions import ClientError, NoCredentialsError + +# Configure logging +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") +logger = logging.getLogger(__name__) + + +# snippet-start:[python.example_code.{service}.Hello] +def hello_{service}(): + """ + Use the AWS SDK for Python (Boto3) to create an {AWS Service} client and + {basic operation description}. + This example uses the default settings specified in your shared credentials + and config files. + """ + try: + # Create service client + {service}_client = boto3.client("{service}") + + # Perform the most basic operation for this service + response = {service}_client.{basic_operation}() + + print("Hello, {AWS Service}!") + # Display appropriate result information + + except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "UnauthorizedOperation": + print("You don't have permission to access {AWS Service}.") + else: + print(f"Couldn't access {AWS Service}. Error: {e}") + except NoCredentialsError: + print("No AWS credentials found. Please configure your credentials.") + except Exception as e: + print(f"An unexpected error occurred: {e}") + + +if __name__ == "__main__": + hello_{service}() +# snippet-end:[python.example_code.{service}.Hello] +``` + +## Hello Examples by Service Type + +### List-Based Services (S3, DynamoDB, etc.) +- **Operation**: List primary resources (buckets, tables, etc.) +- **Message**: Show count and names of resources + +### Status-Based Services (GuardDuty, Config, etc.) +- **Operation**: Check service status or list detectors/configurations +- **Message**: Show service availability and basic status + +### Compute Services (EC2, Lambda, etc.) +- **Operation**: List instances/functions or describe regions +- **Message**: Show available resources or regions + +## Validation Requirements +- ✅ **Must run without errors** (with proper credentials) +- ✅ **Must handle credential issues gracefully** +- ✅ **Must display meaningful output** +- ✅ **Must use direct boto3 client calls** +- ✅ **Must include proper snippet tags** + +## Common Patterns +- Always use `boto3.client("{service}")` directly +- Include comprehensive error handling +- Provide user-friendly output messages +- Use appropriate logging levels +- Handle both service-specific and general errors +- Keep it as simple as possible - no additional classes or complexity \ No newline at end of file diff --git a/steering_docs/python-tech/metadata.md b/steering_docs/python-tech/metadata.md new file mode 100644 index 00000000000..15ba4073719 --- /dev/null +++ b/steering_docs/python-tech/metadata.md @@ -0,0 +1,211 @@ +# Python Metadata Generation + +## Purpose +Generate documentation metadata files that integrate with AWS Documentation pipeline for snippet extraction and cross-referencing. + +## Requirements +- **Specification First**: Always check service specification for exact metadata keys +- **Snippet Tags**: Match snippet tags in code exactly +- **Complete Coverage**: Include all actions and scenarios from specification + +## File Structure +``` +.doc_gen/metadata/ +├── {service}_metadata.yaml # Service metadata file +``` + +## Metadata Discovery Process + +### Step 1: Check Service Specification +**CRITICAL**: Always read `scenarios/basics/{service}/SPECIFICATION.md` first for metadata requirements. + +Look for the metadata table: +```markdown +## Metadata + +|action / scenario |metadata file |metadata key | +|--- |--- |--- | +|`CreateDetector` |{service}_metadata.yaml |{service}_CreateDetector | +|`GetDetector` |{service}_metadata.yaml |{service}_GetDetector | +|`Service Basics Scenario` |{service}_metadata.yaml |{service}_Scenario | +``` + +### Step 2: Use Exact Metadata Keys +**NEVER** create custom metadata keys when specification defines them. Use the exact keys from the specification table. + +## Metadata File Pattern +```yaml +# .doc_gen/metadata/{service}_metadata.yaml + +{service}_CreateResource: + title: Create a &{ServiceAbbrev}; resource + title_abbrev: Create a resource + synopsis: create a &{ServiceAbbrev}; resource. + category: Actions + languages: + Python: + versions: + - sdk_version: 3 + github: python/example_code/{service} + excerpts: + - description: + snippet_tags: + - python.example_code.{service}.CreateResource + services: + {service}: {CreateResource} + +{service}_GetResource: + title: Get a &{ServiceAbbrev}; resource + title_abbrev: Get a resource + synopsis: get a &{ServiceAbbrev}; resource. + category: Actions + languages: + Python: + versions: + - sdk_version: 3 + github: python/example_code/{service} + excerpts: + - description: + snippet_tags: + - python.example_code.{service}.GetResource + services: + {service}: {GetResource} + +{service}_Scenario: + title: Get started with &{ServiceAbbrev}; resources + title_abbrev: Get started with resources + synopsis: learn the basics of &{ServiceAbbrev}; by creating resources and managing them. + category: Scenarios + languages: + Python: + versions: + - sdk_version: 3 + github: python/example_code/{service} + excerpts: + - description: Create a {Service} wrapper class to manage operations. + snippet_tags: + - python.example_code.{service}.{Service}Wrapper + - description: Run an interactive scenario demonstrating {Service} basics. + snippet_tags: + - python.example_code.{service}.{Service}Scenario + services: + {service}: {CreateResource, GetResource, ListResources, DeleteResource} + +{service}_Hello: + title: Hello &{ServiceAbbrev}; + title_abbrev: Hello &{ServiceAbbrev}; + synopsis: get started using &{ServiceAbbrev};. + category: Hello + languages: + Python: + versions: + - sdk_version: 3 + github: python/example_code/{service} + excerpts: + - description: + snippet_tags: + - python.example_code.{service}.Hello + services: + {service}: {ListResources} +``` + +## Snippet Tag Requirements + +### Code Snippet Tags +All code must include proper snippet tags that match metadata: + +```python +# snippet-start:[python.example_code.{service}.{ActionName}] +def action_method(self): + """Action implementation""" + pass +# snippet-end:[python.example_code.{service}.{ActionName}] +``` + +### Wrapper Class Tags +```python +# snippet-start:[python.example_code.{service}.{Service}Wrapper] +class {Service}Wrapper: + """Wrapper class implementation""" + pass +# snippet-end:[python.example_code.{service}.{Service}Wrapper] +``` + +### Scenario Tags +```python +# snippet-start:[python.example_code.{service}.{Service}Scenario] +class {Service}Scenario: + """Scenario class implementation""" + pass +# snippet-end:[python.example_code.{service}.{Service}Scenario] +``` + +### Hello Tags +```python +# snippet-start:[python.example_code.{service}.Hello] +def hello_{service}(): + """Hello implementation""" + pass +# snippet-end:[python.example_code.{service}.Hello] +``` + +## Service Abbreviations + +Common service abbreviations for metadata: +- **GuardDuty**: GD +- **DynamoDB**: DDB +- **Simple Storage Service**: S3 +- **Elastic Compute Cloud**: EC2 +- **Identity and Access Management**: IAM +- **Key Management Service**: KMS +- **Simple Notification Service**: SNS +- **Simple Queue Service**: SQS + +## Metadata Categories + +### Actions +Individual service operations (CreateResource, GetResource, etc.) + +### Scenarios +Multi-step workflows demonstrating service usage + +### Hello +Simple introduction examples + +### Cross-service +Examples spanning multiple AWS services + +## Metadata Validation + +### Required Fields +- ✅ **title**: Descriptive title with service abbreviation +- ✅ **title_abbrev**: Shortened title +- ✅ **synopsis**: Brief description of what the example does +- ✅ **category**: Actions, Scenarios, Hello, or Cross-service +- ✅ **languages.Python.versions**: SDK version information +- ✅ **github**: Path to example code +- ✅ **snippet_tags**: Matching tags from code +- ✅ **services**: Service operations used + +### Validation Commands +```bash +# Validate metadata with writeme tool +cd .tools/readmes +python -m writeme --languages Python:3 --services {service} +``` + +## Common Metadata Errors +- ❌ **Custom metadata keys** when specification exists +- ❌ **Mismatched snippet tags** between code and metadata +- ❌ **Missing service operations** in services section +- ❌ **Incorrect github paths** to example code +- ❌ **Wrong service abbreviations** in titles +- ❌ **Missing required fields** in metadata structure + +## Metadata Generation Workflow +1. **Read specification** for exact metadata requirements +2. **Extract metadata table** from specification +3. **Create metadata file** using specification keys +4. **Add snippet tags** to all code files +5. **Validate metadata** with writeme tool +6. **Fix any validation errors** before completion \ No newline at end of file diff --git a/steering_docs/python-tech/orchestration.md b/steering_docs/python-tech/orchestration.md new file mode 100644 index 00000000000..dc02d24ef07 --- /dev/null +++ b/steering_docs/python-tech/orchestration.md @@ -0,0 +1,243 @@ +# Python Code Generation Orchestration + +## Purpose +Coordinate the modular components to generate complete AWS SDK code examples. Each component can be used independently or in sequence. + +## Component Dependencies + +```mermaid +graph TD + A[Knowledge Base Consultation] --> B[Hello Example] + A --> C[Wrapper Class] + A --> D[Scenario] + + C --> E[Tests - Stubber Creation] + E --> F[Tests - Unit Tests] + E --> G[Tests - Integration Tests] + E --> H[Tests - Scenario Tests] + + B --> I[Metadata Generation] + C --> I + D --> I + + I --> J[README Generation] + + K[Service Specification] --> I + K --> C + K --> D +``` + +## Execution Workflows + +### Full Service Implementation +Complete implementation of a new AWS service: + +```bash +# 1. Knowledge Base Consultation (MANDATORY FIRST) +# Use ListKnowledgeBases + QueryKnowledgeBases for standards and patterns + +# 2. Create Service Stubber (MANDATORY BEFORE TESTS) +# Create python/test_tools/{service}_stubber.py +# Add to python/test_tools/stubber_factory.py + +# 3. Generate Core Components +# - Hello example: {service}_hello.py +# - Wrapper class: {service}_wrapper.py +# - Scenario: scenario_{service}_basics.py +# - Requirements: requirements.txt + +# 4. Generate Test Suite +# - conftest.py with ScenarioData +# - test_{service}_wrapper.py +# - test_{service}_scenario.py +# - test_{service}_integration.py + +# 5. Generate Metadata +# - Read service specification for exact metadata keys +# - Create .doc_gen/metadata/{service}_metadata.yaml + +# 6. Generate Documentation +# - Run writeme tool to create/update README.md +``` + +### Individual Component Updates + +#### Update Hello Example Only +```bash +# Focus: hello.md guidance +# Files: {service}_hello.py +# Validation: Run hello example, check output +``` + +#### Update Wrapper Class Only +```bash +# Focus: wrapper.md guidance +# Files: {service}_wrapper.py +# Validation: Run unit tests for wrapper methods +``` + +#### Update Scenario Only +```bash +# Focus: scenario.md guidance +# Files: scenario_{service}_basics.py +# Validation: Run scenario tests, check user interaction +``` + +#### Update Tests Only +```bash +# Focus: tests.md guidance +# Files: All test files in test/ directory +# Validation: Run pytest with all markers +``` + +#### Update Metadata Only +```bash +# Focus: metadata.md guidance +# Files: .doc_gen/metadata/{service}_metadata.yaml +# Validation: Run writeme tool validation +``` + +#### Update Documentation Only +```bash +# Focus: readme.md guidance +# Files: README.md (generated) +# Validation: Check README completeness and accuracy +``` + +## Quality Gates + +### Component-Level Validation +Each component has specific validation requirements: + +#### Hello Example Validation +```bash +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/{service}_hello.py +``` + +#### Wrapper Class Validation +```bash +PYTHONPATH=python:python/example_code/{service} python -c "from {service}_wrapper import {Service}Wrapper; wrapper = {Service}Wrapper.from_client(); print('✅ Wrapper functions working')" +``` + +#### Scenario Validation +```bash +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/scenario_{service}_basics.py +``` + +#### Test Validation +```bash +PYTHONPATH=python:python/example_code/{service} python -m pytest python/example_code/{service}/test/ -m "not integ" -v +PYTHONPATH=python:python/example_code/{service} python -m pytest python/example_code/{service}/test/ -m "integ" -v +``` + +#### Code Quality Validation +```bash +black python/example_code/{service}/ +pylint --rcfile=.github/linters/.python-lint python/example_code/{service}/ +``` + +#### Documentation Validation +```bash +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Python:3 --services {service} +``` + +### Integration Validation +Full integration testing across all components: + +```bash +# 1. All unit tests pass +python -m pytest python/example_code/{service}/test/ -m "not integ" -v + +# 2. All integration tests pass +python -m pytest python/example_code/{service}/test/ -m "integ" -v + +# 3. All examples execute successfully +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/{service}_hello.py +PYTHONPATH=python:python/example_code/{service} python python/example_code/{service}/scenario_{service}_basics.py + +# 4. Code quality passes +black python/example_code/{service}/ +pylint --rcfile=.github/linters/.python-lint python/example_code/{service}/ + +# 5. Documentation generates successfully +cd .tools/readmes && source .venv/bin/activate && python -m writeme --languages Python:3 --services {service} +``` + +## Component Selection Guide + +### When to Use Individual Components + +#### Hello Example Only +- Quick service introduction needed +- Testing basic service connectivity +- Creating minimal working example + +#### Wrapper Class Only +- Need reusable service operations +- Building foundation for other examples +- Focusing on error handling patterns + +#### Scenario Only +- Demonstrating complete workflows +- Educational/tutorial content +- Interactive user experiences + +#### Tests Only +- Improving test coverage +- Adding new test cases +- Fixing test infrastructure + +#### Metadata Only +- Documentation pipeline integration +- Updating snippet references +- Fixing metadata validation errors + +#### Documentation Only +- README updates needed +- Documentation refresh +- Link validation and updates + +### When to Use Full Workflow +- New service implementation +- Complete service overhaul +- Major structural changes +- Initial service setup + +## Error Recovery + +### Component Failure Handling +If any component fails, you can: + +1. **Fix and retry** the specific component +2. **Skip and continue** with other components +3. **Rollback changes** and restart from known good state + +### Common Recovery Scenarios + +#### Test Failures +```bash +# Fix test issues and re-run +python -m pytest python/example_code/{service}/test/ -v --tb=short +``` + +#### Metadata Validation Failures +```bash +# Check metadata syntax +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Validate against specification +# Compare with scenarios/basics/{service}/SPECIFICATION.md +``` + +#### Documentation Generation Failures +```bash +# Check for missing dependencies +cd .tools/readmes && source .venv/bin/activate && pip list + +# Validate metadata first +python -m writeme --languages Python:3 --services {service} --verbose +``` + +This modular approach allows for targeted updates, easier debugging, and more maintainable code generation processes. \ No newline at end of file diff --git a/steering_docs/python-tech/readme_writeme.md b/steering_docs/python-tech/readme_writeme.md new file mode 100644 index 00000000000..e35ed689835 --- /dev/null +++ b/steering_docs/python-tech/readme_writeme.md @@ -0,0 +1,229 @@ +# Python README/WRITEME and Documentation Generation + +## Purpose +Generate and update README files and documentation using the writeme tool to ensure consistency and completeness. + +## Requirements +- **Automated Generation**: Use writeme tool for README generation +- **Metadata Dependency**: Requires complete metadata files +- **Virtual Environment**: Run writeme in isolated environment +- **Validation**: Ensure all documentation is up-to-date + +## File Structure +``` +python/example_code/{service}/ +├── README.md # Generated service README +├── requirements.txt # Dependencies +└── {service}_metadata.yaml # Metadata (in .doc_gen/metadata/) +``` + +## README Generation Process + +### Step 1: Setup Writeme Environment +```bash +cd .tools/readmes + +# Create virtual environment +python -m venv .venv + +# Activate environment (Linux/macOS) +source .venv/bin/activate + +# Activate environment (Windows) +.venv\Scripts\activate + +# Install dependencies +python -m pip install -r requirements_freeze.txt +``` + +### Step 2: Generate README +```bash +# Generate README for specific service +python -m writeme --languages Python:3 --services {service} +``` + +### Step 3: Validate Generation +- ✅ **README.md created/updated** in service directory +- ✅ **No generation errors** in writeme output +- ✅ **All examples listed** in README +- ✅ **Proper formatting** and structure +- ✅ **Working links** to code files + +## README Content Structure + +### Generated README Sections +1. **Service Overview**: Description of AWS service +2. **Code Examples**: List of available examples +3. **Prerequisites**: Setup requirements +4. **Installation**: Dependency installation +5. **Usage**: How to run examples +6. **Tests**: Testing instructions +7. **Additional Resources**: Links to documentation + +### Example README Content +```markdown +# {AWS Service} code examples for the SDK for Python + +## Overview + +This is a workspace where you can find the following AWS SDK for Python (Boto3) +{AWS Service} examples. + +## ⚠ Important + +* Running this code might result in charges to your AWS account. +* Running the tests might result in charges to your AWS account. +* We recommend that you grant your code least privilege. + +## Code examples + +### Actions + +The following examples show you how to perform actions using the AWS SDK for Python (Boto3). + +* [Create a resource](action_file.py#L123) (`CreateResource`) +* [Get a resource](action_file.py#L456) (`GetResource`) + +### Scenarios + +The following examples show you how to implement common scenarios. + +* [Get started with resources](scenario_file.py) - Learn the basics by creating and managing resources. + +### Hello + +* [Hello {Service}](hello_file.py) - Get started with {AWS Service}. + +## Prerequisites + +- You must have an AWS account, and have your default credentials and AWS Region configured. +- Python 3.6 or later +- Boto3 1.26.137 or later +- PyTest 5.3.5 or later (to run unit tests) + +## Install + +Install the prerequisites using pip: + +``` +pip install -r requirements.txt +``` + +## Run the examples + +### Instructions + +All examples can be run individually. For example: + +``` +python hello_{service}.py +``` + +### Hello {Service} + +This example shows you how to get started using {AWS Service}. + +``` +python hello_{service}.py +``` + +### Get started with {Service} resources + +This interactive scenario runs at a command prompt and shows you how to use {AWS Service} to do the following: + +1. Create a resource +2. Use the resource +3. Clean up resources + +``` +python scenario_{service}_basics.py +``` + +## Run the tests + +Unit tests in this module use the botocore Stubber. This captures requests before +they are sent to AWS, and returns a mocked response. To run all of the tests, +run the following in your [GitHub root]/python/example_code/{service} folder. + +``` +python -m pytest +``` + +## Additional resources + +- [{AWS Service} User Guide](https://docs.aws.amazon.com/{service}/latest/ug/) +- [{AWS Service} API Reference](https://docs.aws.amazon.com/{service}/latest/APIReference/) +- [AWS SDK for Python ({AWS Service})](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/{service}.html) +``` + +## Documentation Dependencies + +### Required Files for README Generation +- ✅ **Metadata file**: `.doc_gen/metadata/{service}_metadata.yaml` +- ✅ **Code files**: All referenced Python files must exist +- ✅ **Snippet tags**: All snippet tags in metadata must exist in code +- ✅ **Requirements file**: `requirements.txt` with dependencies + +### Metadata Integration +The writeme tool uses metadata to: +- Generate example lists and descriptions +- Create links to specific code sections +- Include proper service information +- Format documentation consistently + +## Troubleshooting README Generation + +### Common Issues +- **Missing metadata**: Ensure metadata file exists and is valid +- **Broken snippet tags**: Verify all snippet tags exist in code +- **File not found**: Check all file paths in metadata +- **Invalid YAML**: Validate metadata YAML syntax + +### Error Resolution +```bash +# Check for metadata errors +python -m writeme --languages Python:3 --services {service} --verbose + +# Validate specific metadata file +python -c "import yaml; yaml.safe_load(open('.doc_gen/metadata/{service}_metadata.yaml'))" + +# Check for missing snippet tags +grep -r "snippet-start" python/example_code/{service}/ +``` + +## README Maintenance + +### When to Regenerate README +- ✅ **After adding new examples** +- ✅ **After updating metadata** +- ✅ **After changing code structure** +- ✅ **Before committing changes** +- ✅ **During regular maintenance** + +### README Quality Checklist +- ✅ **All examples listed** and properly linked +- ✅ **Prerequisites accurate** and complete +- ✅ **Installation instructions** work correctly +- ✅ **Usage examples** are clear and correct +- ✅ **Links functional** and point to right locations +- ✅ **Formatting consistent** with other services + +## Integration with CI/CD + +### Automated README Validation +```bash +# In CI/CD pipeline, validate README is up-to-date +cd .tools/readmes +source .venv/bin/activate +python -m writeme --languages Python:3 --services {service} --check + +# Exit with error if README needs updates +if git diff --exit-code python/example_code/{service}/README.md; then + echo "README is up-to-date" +else + echo "README needs to be regenerated" + exit 1 +fi +``` + +This ensures documentation stays synchronized with code changes. \ No newline at end of file diff --git a/steering_docs/python-tech/tests.md b/steering_docs/python-tech/tests.md new file mode 100644 index 00000000000..27220bb1a88 --- /dev/null +++ b/steering_docs/python-tech/tests.md @@ -0,0 +1,305 @@ +# Python Test Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Python-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Python-premium-KB", "Python implementation patterns testing") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate comprehensive test suites including unit tests, integration tests, and scenario tests with proper stubbing and AWS data structures. + +## Requirements +- **MANDATORY**: Create service stubber BEFORE conftest.py +- **Complete Data**: Use complete AWS data structures in tests +- **Proper Markers**: Use pytest markers for test categorization +- **Error Coverage**: Test all error conditions from specification + +## File Structure +``` +python/example_code/{service}/test/ +├── conftest.py # Test configuration and fixtures +├── test_{service}_wrapper.py # Unit tests for wrapper +└── test_{service}_integration.py # Integration test that runs entire scenario +``` + +## MANDATORY Pre-Test Setup + +### Step 1: Create Service Stubber (REQUIRED FIRST) +```python +# python/test_tools/{service}_stubber.py +from test_tools.example_stubber import ExampleStubber + +class {Service}Stubber(ExampleStubber): + """Stub functions for {AWS Service} unit tests.""" + + def __init__(self, {service}_client: client, use_stubs=True) -> None: + super().__init__({service}_client, use_stubs) + + def stub_{action_name}(self, param: str, response_data: dict, error_code: str = None) -> None: + """Stub the {action_name} function.""" + expected_params = {"Parameter": param} + response = response_data + self._stub_bifurcator( + "{action_name}", expected_params, response, error_code=error_code + ) +``` + +### Step 2: Add to Stubber Factory +```python +# python/test_tools/stubber_factory.py +from test_tools.{service}_stubber import {Service}Stubber + +# Add to imports and factory function +elif service_name == "{service}": + return {Service}Stubber +``` + +### Step 3: Create conftest.py with ScenarioData +```python +# python/example_code/{service}/test/conftest.py +import sys +import boto3 +import pytest + +sys.path.append("../..") +from test_tools.fixtures.common import * +from {service}_wrapper import {Service}Wrapper + +class ScenarioData: + """Encapsulates data for {Service} scenario tests.""" + + def __init__(self, {service}_client, {service}_stubber): + self.{service}_client = {service}_client + self.{service}_stubber = {service}_stubber + self.wrapper = {Service}Wrapper({service}_client) + +@pytest.fixture +def scenario_data(make_stubber): + """Creates a ScenarioData object for {Service} scenario tests.""" + {service}_client = boto3.client("{service}", region_name="us-east-1") + {service}_stubber = make_stubber({service}_client) + return ScenarioData({service}_client, {service}_stubber) +``` + +## Unit Test Pattern +```python +# test_{service}_wrapper.py +import pytest +import boto3 +from botocore.exceptions import ClientError +from {service}_wrapper import {Service}Wrapper + +@pytest.mark.parametrize("error_code", [None, "BadRequestException", "InternalServerErrorException"]) +def test_{action_name}(make_stubber, error_code): + {service}_client = boto3.client("{service}", region_name="us-east-1") + {service}_stubber = make_stubber({service}_client) + {service}_wrapper = {Service}Wrapper({service}_client) + + # Test parameters + param_value = "test-value" + expected_response = {"ResponseKey": "response-value"} + + # Setup stub + {service}_stubber.stub_{action_name}(param_value, expected_response, error_code) + + if error_code is None: + result = {service}_wrapper.{action_name}(param_value) + assert result["ResponseKey"] == "response-value" + else: + with pytest.raises(ClientError) as exc_info: + {service}_wrapper.{action_name}(param_value) + assert exc_info.value.response["Error"]["Code"] == error_code +``` + +## Complete AWS Data Structures + +### CRITICAL: Use Complete AWS Response Data +```python +# ❌ WRONG - Minimal data that fails validation +findings = [{"Id": "finding-1", "Type": "SomeType", "Severity": 8.0}] + +# ✅ CORRECT - Complete AWS data structure +findings = [{ + "Id": "finding-1", + "AccountId": "123456789012", + "Arn": "arn:aws:service:region:account:resource/id", + "Type": "SomeType", + "Severity": 8.0, + "CreatedAt": "2023-01-01T00:00:00.000Z", + "UpdatedAt": "2023-01-01T00:00:00.000Z", + "Region": "us-east-1", + "SchemaVersion": "2.0", + "Resource": {"ResourceType": "Instance"} +}] +``` + +## Integration Test Pattern +The integration test should run the entire scenario end-to-end against real AWS services: + +```python +# test_{service}_integration.py +import pytest +import time +from unittest.mock import patch +from {service}_wrapper import {Service}Wrapper +from scenario_{service}_basics import {Service}Scenario + +@pytest.mark.integ +def test_scenario_complete_integration(): + """Test the complete scenario flow against real AWS services.""" + {service}_wrapper = {Service}Wrapper.from_client() + scenario = {Service}Scenario({service}_wrapper) + + # Mock user inputs for automated testing + with patch('demo_tools.question.ask') as mock_ask: + # Configure responses for the scenario questions + mock_ask.side_effect = [ + False, # Don't use existing resource + False, # Don't show detailed info + True, # Perform cleanup + ] + + # Mock time.sleep to speed up test + with patch('time.sleep'): + # Run the complete scenario + scenario.run_scenario() + + # Verify scenario completed successfully + # (cleanup should have been performed, so resource_id should be handled) + assert True # Scenario completed without exceptions + +@pytest.mark.integ +def test_scenario_with_existing_resources(): + """Test scenario when existing resources are present.""" + {service}_wrapper = {Service}Wrapper.from_client() + scenario = {Service}Scenario({service}_wrapper) + + # First create a resource to test "existing resource" path + resource_id = None + try: + resource_id = {service}_wrapper.create_resource(enable=True) + + with patch('demo_tools.question.ask') as mock_ask: + mock_ask.side_effect = [ + True, # Use existing resource + False, # Don't show detailed info + False, # Don't delete resource (we'll clean up manually) + ] + + with patch('time.sleep'): + scenario.run_scenario() + + # Verify scenario used existing resource + assert scenario.resource_id == resource_id + + finally: + # Manual cleanup + if resource_id: + try: + {service}_wrapper.delete_resource(resource_id) + except Exception: + pass # Ignore cleanup errors +``` + +## Additional Integration Test Patterns (Optional) +If needed, you can add specific wrapper method tests: + +```python +@pytest.mark.integ +def test_{action_name}_integration(): + """Test {action} against real AWS.""" + {service}_wrapper = {Service}Wrapper.from_client() + + # This should not raise an exception + result = {service}_wrapper.{action_name}() + + # Verify result structure + assert isinstance(result, expected_type) + +@pytest.mark.integ +def test_resource_lifecycle_integration(): + """Test creating, using, and deleting a resource.""" + {service}_wrapper = {Service}Wrapper.from_client() + resource_id = None + + try: + # Create resource + resource_id = {service}_wrapper.create_resource() + assert resource_id is not None + + # Use resource + result = {service}_wrapper.get_resource(resource_id) + assert result is not None + + finally: + # Clean up + if resource_id: + try: + {service}_wrapper.delete_resource(resource_id) + except ClientError: + pass # Ignore cleanup errors +``` + +## Test Execution Commands + +### Unit Tests +```bash +PYTHONPATH=python:python/example_code/{service} python -m pytest python/example_code/{service}/test/ -m "not integ" -v +``` + +### Integration Tests (Runs Complete Scenario) +```bash +PYTHONPATH=python:python/example_code/{service} python -m pytest python/example_code/{service}/test/ -m "integ" -v +``` + +## Test Requirements Checklist +- ✅ **Service stubber created FIRST** (before conftest.py) +- ✅ **Stubber added to factory** (stubber_factory.py) +- ✅ **ScenarioData class** for complex services +- ✅ **Complete AWS data structures** in all tests +- ✅ **Proper pytest markers** (`@pytest.mark.integ`) +- ✅ **Error condition coverage** per specification +- ✅ **Integration test runs complete scenario** end-to-end +- ✅ **Integration test cleanup** (try/finally blocks) +- ✅ **Region specification** (region_name="us-east-1") +- ✅ **Mock user inputs** for automated scenario testing + +## Integration Test Focus + +### Primary Test: Complete Scenario Integration +The main integration test should: +- ✅ **Run the entire scenario** from start to finish +- ✅ **Mock user inputs** to automate the interactive parts +- ✅ **Test against real AWS** services (not stubs) +- ✅ **Handle cleanup properly** to avoid resource leaks +- ✅ **Test multiple paths** (new resources, existing resources) + +### Test Structure Priority +1. **Integration Test** - Most important, tests complete workflow +2. **Unit Tests** - Test individual wrapper methods +3. **Additional Integration Tests** - Optional, for specific edge cases + +## Common Test Failures to Avoid +- ❌ Creating conftest.py before service stubber +- ❌ Using incomplete AWS data structures +- ❌ Missing pytest markers for integration tests +- ❌ Not handling cleanup in integration tests +- ❌ Forgetting to set AWS region in test clients +- ❌ Not testing all error conditions from specification +- ❌ Not mocking user inputs in scenario integration tests +- ❌ Not testing the complete scenario end-to-end \ No newline at end of file diff --git a/steering_docs/python-tech/wrapper.md b/steering_docs/python-tech/wrapper.md new file mode 100644 index 00000000000..e4e11c92303 --- /dev/null +++ b/steering_docs/python-tech/wrapper.md @@ -0,0 +1,244 @@ +# Python Service Wrapper Generation + +## MANDATORY: Knowledge Base Consultation (FIRST STEP) +**🚨 CRITICAL - Must be completed BEFORE any code generation** + +```bash +# Step 1: List available knowledge bases +ListKnowledgeBases() + +# Step 2: Query coding standards (REQUIRED) +QueryKnowledgeBases("coding-standards-KB", "Python-code-example-standards") + +# Step 3: Query implementation patterns (REQUIRED) +QueryKnowledgeBases("Python-premium-KB", "Python implementation patterns") + +# Step 4: AWS service research (REQUIRED) +search_documentation("What is [AWS Service] and what are its key API operations?") +read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]") +``` + +**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE** + +## Purpose +Generate service wrapper classes that encapsulate AWS service functionality with proper error handling and logging. + +## Requirements +- **MANDATORY**: Every service MUST have a wrapper class +- **Error Handling**: Handle service-specific errors appropriately +- **Logging**: Include comprehensive logging for all operations +- **Type Hints**: Use type annotations for better code clarity + +## File Structure +``` +python/example_code/{service}/ +├── {service}_wrapper.py # Service wrapper class +``` + +## Wrapper Class Pattern +```python +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Purpose + +Shows how to use the AWS SDK for Python (Boto3) with {AWS Service} to +{service description and main use cases}. +""" + +import logging +import boto3 +from botocore.exceptions import ClientError +from typing import Dict, List, Optional, Any + +logger = logging.getLogger(__name__) + + +# snippet-start:[python.example_code.{service}.{Service}Wrapper] +class {Service}Wrapper: + """Encapsulates {AWS Service} functionality.""" + + def __init__(self, {service}_client: boto3.client): + """ + :param {service}_client: A Boto3 {AWS Service} client. + """ + self.{service}_client = {service}_client + + @classmethod + def from_client(cls): + """ + Creates a {Service}Wrapper instance with a default {AWS Service} client. + + :return: An instance of {Service}Wrapper. + """ + {service}_client = boto3.client("{service}") + return cls({service}_client) +# snippet-end:[python.example_code.{service}.{Service}Wrapper] + + # Individual action methods follow... +``` + +## Action Method Pattern +```python + # snippet-start:[python.example_code.{service}.{ActionName}] + def {action_method}(self, param: str) -> Dict[str, Any]: + """ + {Action description}. + + :param param: Parameter description. + :return: Response description. + """ + try: + response = self.{service}_client.{action_name}(Parameter=param) + logger.info(f"{Action} completed successfully") + return response + except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "SpecificError": + logger.error("Specific error handling message") + elif error_code == "AnotherSpecificError": + logger.error("Another specific error handling message") + else: + logger.error(f"Error in {action}: {e}") + raise + # snippet-end:[python.example_code.{service}.{ActionName}] +``` + +## Paginator Pattern for List Operations +```python + # snippet-start:[python.example_code.{service}.List{Resources}] + def list_{resources}(self) -> List[Dict[str, Any]]: + """ + Lists all {resources} using pagination to retrieve complete results. + + :return: A list of all {resources}. + """ + try: + # Use paginator when available + paginator = self.{service}_client.get_paginator('list_{resources}') + {resources} = [] + + for page in paginator.paginate(): + {resources}.extend(page.get('{Resources}', [])) + + logger.info(f"Retrieved {len({resources})} {resources}") + return {resources} + except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "BadRequestException": + logger.error("Invalid request parameters for listing {resources}") + else: + logger.error(f"Error listing {resources}: {e}") + raise + # snippet-end:[python.example_code.{service}.List{Resources}] +``` + +## Paginator with Parameters Pattern +```python + # snippet-start:[python.example_code.{service}.List{Resources}WithFilter] + def list_{resources}_with_filter(self, filter_criteria: Optional[Dict] = None) -> List[Dict[str, Any]]: + """ + Lists {resources} with optional filtering, using pagination. + + :param filter_criteria: Optional criteria to filter results. + :return: A list of filtered {resources}. + """ + try: + paginator = self.{service}_client.get_paginator('list_{resources}') + {resources} = [] + + # Build pagination parameters + paginate_params = {} + if filter_criteria: + paginate_params['FilterCriteria'] = filter_criteria + + for page in paginator.paginate(**paginate_params): + {resources}.extend(page.get('{Resources}', [])) + + logger.info(f"Retrieved {len({resources})} filtered {resources}") + return {resources} + except ClientError as e: + logger.error(f"Error listing {resources} with filter: {e}") + raise + # snippet-end:[python.example_code.{service}.List{Resources}WithFilter] +``` + +## Error Handling Requirements + +### Service-Specific Errors +Based on the service specification, handle these error types: +- **BadRequestException**: Validate input parameters +- **InternalServerErrorException**: Retry with exponential backoff +- **ResourceNotFoundException**: Handle missing resources gracefully +- **AccessDeniedException**: Provide clear permission guidance + +### Error Handling Pattern +```python +try: + response = self.{service}_client.operation() + return response +except ClientError as e: + error_code = e.response["Error"]["Code"] + if error_code == "BadRequestException": + logger.error("Validate input parameters and notify user") + elif error_code == "InternalServerErrorException": + logger.error("Retry operation with exponential backoff") + else: + logger.error(f"Error in operation: {e}") + raise +``` + +## Wrapper Class Requirements +- ✅ **ALWAYS** include proper logging for all operations +- ✅ **ALWAYS** provide `from_client()` class method +- ✅ **ALWAYS** handle service-specific errors per specification +- ✅ **ALWAYS** include comprehensive docstrings +- ✅ **ALWAYS** use type hints for parameters and returns +- ✅ **ALWAYS** follow the established naming conventions +- ✅ **ALWAYS** use paginators for list operations when available +- ✅ **ALWAYS** retrieve complete results, not just first page + +## Method Naming Conventions +- Use snake_case for method names +- Match AWS API operation names (e.g., `list_buckets` for `ListBuckets`) +- Use descriptive parameter names +- Return appropriate data types (Dict, List, str, etc.) + +## Pagination Requirements +- **MANDATORY**: Use paginators when available for list operations +- **Complete Results**: Ensure all pages are retrieved, not just first page +- **Efficient**: Use boto3 paginators instead of manual pagination + +## Paginator Usage Guidelines + +### When to Use Paginators +- ✅ **List Operations**: Always use for operations that return lists of resources +- ✅ **Large Result Sets**: Essential for services that may return many items +- ✅ **Complete Data**: Ensures all results are retrieved, not just first page + +### How to Check for Paginator Availability +```python +# Check if paginator exists for an operation +try: + paginator = self.{service}_client.get_paginator('list_{resources}') + # Use paginator +except Exception: + # Fall back to regular API call if paginator not available + response = self.{service}_client.list_{resources}() +``` + +### Common Paginator Operations +- `list_buckets` → Use paginator if available +- `list_objects` → Always use paginator (can return thousands of objects) +- `list_tables` → Use paginator for complete results +- `describe_instances` → Use paginator for large environments +- `list_functions` → Use paginator for complete function list + +## Documentation Requirements +- Include module-level docstring explaining service purpose +- Document all parameters with type and description +- Document return values with type and description +- Include usage examples in docstrings where helpful +- Use proper snippet tags for documentation generation +- Document pagination behavior in list method docstrings \ No newline at end of file diff --git a/steering_docs/rust-tech.md b/steering_docs/rust-tech.md new file mode 100644 index 00000000000..90826c4267d --- /dev/null +++ b/steering_docs/rust-tech.md @@ -0,0 +1,166 @@ +# Rust Technology Stack & Build System + +## Rust SDK v1 Development Environment + +### Build Tools & Dependencies +- **Build System**: Cargo +- **Testing Framework**: Built-in Rust testing +- **Package Manager**: Cargo with crates.io +- **SDK Version**: AWS SDK for Rust v1 +- **Rust Version**: Latest stable Rust + +### Common Build Commands + +```bash +# Development +cargo check # Check compilation without building +cargo build # Build project +cargo build --release # Build optimized release version + +# Testing +cargo test # Run all tests +cargo test --test integration # Run integration tests +cargo test -- --nocapture # Run tests with output + +# Execution +cargo run --bin hello # Run hello scenario +cargo run --bin getting-started # Run getting started scenario +cargo run --bin {scenario-name} # Run specific scenario +``` + +### Rust-Specific Pattern Requirements + +**CRITICAL**: Rust examples follow a specific directory structure pattern. Always examine existing Rust examples (like EC2) before creating new ones. + +#### Correct Structure for Rust Scenarios +``` +rustv1/examples/{service}/ +├── Cargo.toml +├── README.md +├── src/ +│ ├── lib.rs +│ ├── {service}.rs # Service wrapper +│ ├── bin/ +│ │ ├── hello.rs # MANDATORY: Hello scenario +│ │ ├── {action-one}.rs # Individual action file +│ │ ├── {action-two}.rs # Individual action file, etc. +│ │ └── {scenario-name}.rs # Other scenario entry points +│ └── {scenario_name}/ +│ ├── mod.rs +│ ├── scenario.rs # Main scenario logic +│ └── tests/ +│ └── mod.rs # Integration tests +``` + +#### Key Structural Points +- **MANDATORY**: Every service must include `src/bin/hello.rs` as the simplest example +- **Follow the EC2 example structure exactly** - it's the canonical pattern +- **Service wrapper goes in `src/{service}.rs`** (e.g., `src/comprehend.rs`) +- **Tests go in `{scenario_name}/tests/mod.rs`** for integration testing +- **Hello scenario**: Should demonstrate the most basic service operation + +#### File Naming Conventions +- Use snake_case for all Rust files and directories +- Binary files: `{action}.rs` in `src/bin/` directory +- Service modules: `{service}.rs` in `src/` directory +- Scenario modules: `{scenario_name}/mod.rs` and `scenario.rs` + +#### Hello Scenario Structure +- **File location**: `src/bin/hello.rs` +- **Function structure**: `main()` function as entry point with `tokio::main` attribute +- **Documentation**: Include module-level documentation explaining the hello example + +#### Code Structure Standards +- **Modules**: Use `mod.rs` files for module organization +- **Functions**: Use snake_case for function names +- **Structs/Enums**: Use PascalCase for type names +- **Constants**: Use UPPER_SNAKE_CASE for constants +- **Async/Await**: Use `tokio` runtime for async operations + +#### Error Handling Patterns +```rust +use aws_sdk_s3::{Client, Error}; +use aws_config::meta::region::RegionProviderChain; + +#[tokio::main] +async fn main() -> Result<(), Error> { + let region_provider = RegionProviderChain::default_provider().or_else("us-east-1"); + let config = aws_config::from_env().region(region_provider).load().await; + let client = Client::new(&config); + + match client.list_buckets().send().await { + Ok(response) => { + // Handle successful response + println!("Buckets: {:?}", response.buckets()); + Ok(()) + } + Err(e) => { + // Handle error + eprintln!("Error: {}", e); + Err(e) + } + } +} +``` + +#### Testing Standards +- **Integration tests**: Place in `{scenario_name}/tests/mod.rs` +- **Unit tests**: Include `#[cfg(test)]` modules in source files +- **Async testing**: Use `#[tokio::test]` for async test functions +- **Test naming**: Use descriptive function names with snake_case + +#### Cargo.toml Configuration +```toml +[package] +name = "{service}-examples" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "hello" +path = "src/bin/hello.rs" + +[[bin]] +name = "{action-name}" +path = "src/bin/{action-name}.rs" + +[dependencies] +aws-config = "1.0" +aws-sdk-{service} = "1.0" +tokio = { version = "1.0", features = ["full"] } +tracing-subscriber = "0.3" +``` + +#### Documentation Requirements +- **Module documentation**: Use `//!` for module-level docs +- **Function documentation**: Use `///` for function documentation +- **Inline comments**: Explain complex AWS service interactions +- **README sections**: Include Cargo setup and execution instructions + +### Language-Specific Pattern Errors to Avoid +- ❌ **NEVER assume file naming patterns** without checking existing examples +- ❌ **NEVER skip the mandatory `src/bin/hello.rs` file** +- ❌ **NEVER use camelCase for Rust identifiers** +- ❌ **NEVER ignore proper error handling with Result types** +- ❌ **NEVER forget to use async/await for AWS operations** + +### Best Practices +- ✅ **ALWAYS examine `rustv1/examples/ec2/` structure first** +- ✅ **ALWAYS include the mandatory hello scenario** +- ✅ **ALWAYS use snake_case naming conventions** +- ✅ **ALWAYS handle errors with Result types and proper error propagation** +- ✅ **ALWAYS use tokio runtime for async AWS operations** +- ✅ **ALWAYS follow the established directory structure exactly** + +### Cargo Workspace Integration +- **Workspace member**: Each service example is a workspace member +- **Shared dependencies**: Common dependencies managed at workspace level +- **Build optimization**: Shared target directory for faster builds + +### Integration with Knowledge Base +Before creating Rust code examples: +1. Query `coding-standards-KB` for "Rust-code-example-standards" +2. Query `Rust-premium-KB` for "Rust implementation patterns" +3. **CRITICAL**: Always examine existing EC2 example structure as canonical pattern +4. Follow KB-documented patterns for Cargo project structure and module organization +5. Validate against existing Rust examples only after KB consultation \ No newline at end of file